//#include <algorithm>
#include "cmduserinfo.h"
#include "../cmd/cmdselectdatafromdbsvr.h"
#include "../mainctrl.h"
#include "../cmd/dataprepare.h"
#include "../map/CMapView.h"
#include "../maintask/CTaskMgr.h"
#include "../partner/CPartnerMgr.h"
#include "../matrix/CMatrixMgr.h"
#include "../instance/CInstanceMgr.h"
#include "../simpleconfig/CRoleConfigMgr.h"
#include "MsgMoveTo.pb.h"
#include "MsgStorage.pb.h"
#include "MsgMapInfo.pb.h"
#include "MsgMuse.pb.h"
#include "MsgClan.pb.h"
#include "MsgGarden.pb.h"
#include "MsgSoul.pb.h"
#include "../clan/CClanMgr.h"
#include "../shop/CShopMgr.h"
#include "../garden/CGardenMgr.h"
#include "../soul/CSoulMgr.h"
#include "../cmd/cmdapi.h"
#include "../cmdinner/CCmdInnerQQFriend.h"
#include "../cmdinner/CCmdInnerUserLogin.h"
#include "MsgPartner.pb.h"
#include "MsgMatrix.pb.h"
#include "net/CTMD5.h"

CT_REGISTER_ASYNCCMD(ID_MAIN_LOGIN , CCmdLogin);

int CCmdLogin::Do(void* pData)
{
    //int iRet = 0;
    CT_ASSERT(pData);

    //解析消息
    CCmdPBDoParam* pstParam = (CCmdPBDoParam*) pData;
    pstMainCtrl = (CMainCtrl*) pstParam->m_pMain;

    if (pstParam->m_pstMsgHead->msgid() != ID_MAIN_LOGIN ||
        pstParam->m_pstMsgHead->msgtype() != CSMsgDef::EMT_REQUEST)
    {
        CT_ERROR(("Cmd Stat Err Cmd=%d CmdID=%d Tpye=%d",
            ID_MAIN_LOGIN,
            pstParam->m_pstMsgHead->msgid(),
            pstParam->m_pstMsgHead->msgtype()));
        return Done(RET_SYS_ERROR);
    }

    stMsgHead = *(pstParam->m_pstMsgHead);
    stEnpHead = *(pstParam->m_pstEnpHead);
    int iRet = pstMainCtrl->DecodePBMsg(stReq, pstParam);
    if (iRet)
    {
        CT_ERROR((""));
        return AnsClients(iRet);
    }
    //消息解析结束

    CTKeyValue stPara;
    stPara.ParseFromHttpParam(stReq.params().c_str(), stReq.params().length(), false);

    bIsCheckFromMarket = false;
    if (stReq.open_id() != "")
    {
        bIsTencentLogin = true;
        bIsCheckLogin = false;
        bIsCheckInvited = false;
        bIsFromMarket = false;

        stTencentApiKeyValue.SetValue("openid", stReq.open_id().c_str());
        stTencentApiKeyValue.SetValue("openkey", stReq.open_key().c_str());
        stTencentApiKeyValue.SetValue("pf", stReq.pf().c_str());
        stTencentApiKeyValue.SetValue("appid", CONF->AppID());
        stTencentApiKeyValue.SetValue("pfkey", stReq.pfkey().c_str());
        stTencentApiKeyValue.SetValue("app_contract_id", "");

        if ((0 == strcmp(stReq.pf().c_str(), "qzone"))
            || (0 == strcmp(stReq.pf().c_str(), "pengyou"))
            || (0 == strcmp(stReq.pf().c_str(), "website")))
        {
            bIsCheckFromMarket = true;
        }        

        struct in_addr ip;
        ip.s_addr = stEnpHead.uiRemoteIP;
        stTencentApiKeyValue.SetValue("userip",inet_ntoa(ip));

        szUserToken.Set("%s", stReq.open_id().c_str());
    }
    else if (stReq.platform() == "32wan")
    {
        bIs32WanLogin = true;

        if (0 != strncmp(stPara.GetValue("isadult"), "1", 1))
        {
            CT_ERROR((""));
            return AnsClients(ERROR_NOT_ADULT);
        }
        
        //检查登录
        std::string s = stPara.GetValue("username");
        s += stPara.GetValue("serverid");
        s += stPara.GetValue("isadult");
        s += stPara.GetValue("time");
        s += CONF->Wan32Key();

        //if (string(stPara.GetValue("flag")) != CTMD5::GetMD5(s.c_str(), s.length()))
        if (0 != strncmp(stPara.GetValue("flag"), CTMD5::GetMD5(s.c_str(), s.length()), 32))
        {
            CT_ERROR(("%s %s %s", s.c_str(), CTMD5::GetMD5(s.c_str(), s.length()), stPara.GetValue("flag")));
            return AnsClients(RET_NOT_LOGIN);
        }

        bIsCheckLogin = true;
        bIsCheckInvited = true;

        szUserToken.Set("%s", stPara.GetValue("username"));
    }
    else if (stReq.platform() == "yd10086")
    {
        bIsYD10086Login = true;

        if (0 != strncmp(stPara.GetValue("isadult"), "1", 1))
        {
            CT_ERROR((""));
            return AnsClients(ERROR_NOT_ADULT);
        }
        
        //检查登录
        std::string s = stPara.GetValue("username");
        s += stPara.GetValue("serverid");
        s += stPara.GetValue("isadult");
        s += stPara.GetValue("time");
        s += CONF->Wan32Key();

        if (string(stPara.GetValue("flag")) != CTMD5::GetMD5(s.c_str(), s.length()))
        {
            CT_ERROR((""));
            return AnsClients(RET_NOT_LOGIN);
        }

        bIsCheckLogin = true;
        bIsCheckInvited = true;

        szUserToken.Set("%s", stPara.GetValue("username"));
    }
    else
    {
#ifdef _DEBUG
        bIsTencentLogin = false;
        bIsCheckLogin = true;
        bIsCheckInvited = true;
        bIsFromMarket = true;

        stTencentApiKeyValue.SetValue("pf", stReq.pf().c_str());
        szUserToken.Set("%s", stReq.user_token().c_str());
        stTencentApiKeyValue.SetValue("app_contract_id", "");

        //版署账号检查
        //iRet = pstMainCtrl->m_stSpecialAccountMgr.CheckAccount( stReq.user_token().c_str(), stReq.passwd().c_str() );
        //if( iRet<0 )
        //{
            //CT_ERROR((""));
            //return AnsClients( RET_SYS_PB_ILLEGAL_USER );
        //}

#else
        CT_ERROR((""));
        return AnsClients(RET_SYS_ERROR);
#endif
    }

    if (pstMainCtrl->m_stPlayerOnline.GetOnlineCount() >= MAX_PLAYER_ONLINE)
    {
        CT_ERROR((""));
        return AnsClients(ERROR_ONLINE_FULL);
    }

    CT_TRACE(("login , user token %s", szUserToken()));

    bIsNewbie = false;
    bHasInvitedInfo = false;
    
    return LogicDo(RET_OK);
}

int CCmdLogin::CallBack(int iRet)
{
    CCmdSelectDataFromDBSvr* pstCmd = (CCmdSelectDataFromDBSvr*)m_pstChild;

    if (pstCmd->stAns.stResult.iResultID == RET_NO_RECORDER)
    {
        bIsNewbie = true;

        if (pstMainCtrl->m_stZoneOnlineData._stZoneData._chStopOpenRegist > 0)
        {
            return AnsClients(ERROR_SYS_STOP_OPEN_REGIST);
        }

        //检查是否可以注册
        if (pstMainCtrl->m_stPlayerSnsCommInfoHash.Size(pstMainCtrl->m_stPlayerSnsCommInfoHash.USED_LIST) >= MAX_REGISTER_PLAYER)
        {
            return AnsClients(RET_SYS_USER_FULL);
        }

        //没有找到，注册
        CPlayerBaseInfo stPlayerBaseInfo;
        CPlayerDetailInfo stPlayerDetailInfo;
        CPlayerDetailInfoEx1 stPlayerDetailInfoEx1;
        CPlayerSnsDetailInfo stPlayerSnsDetailInfo;
        CUnactPartnerInfo stPlayerUnactPartnerInfo;

        stPlayerBaseInfo._sUserToken = szUserToken;

        int iIndex = pstMainCtrl->m_stUserTokenToGID.HashFind(szUserToken);
        if (iIndex >= 0)
        {
            return AnsClients(ERROR_HAS_REGISTER);
        }

        stPlayerBaseInfo._uiGID = pstMainCtrl->m_stRoleMgr.GetNewGID();
        pstMainCtrl->m_auiAllRegisterGID.AddOneItem(stPlayerBaseInfo._uiGID);

        //player存入hash
        iIndex = pstMainCtrl->m_stPlayerBaseInfoHash.HashFind(stPlayerBaseInfo._uiGID);
        if (iIndex >= 0)
        {
            CT_ERROR(("find duplicate gid %u", stPlayerBaseInfo._uiGID));
            return AnsClients(RET_SYSTEM_FAIL);
        }

        //角色信息初始化
        stPlayerBaseInfo._ucIsInited = 0;  //设置成未初始化

        //角色信息初始化结束

        iIndex = pstMainCtrl->m_stPlayerBaseInfoHash.HashAlloc(stPlayerBaseInfo._uiGID);
        if (iIndex < 0)
        {
            CT_ERROR(("alloc fail"));
            return AnsClients(RET_SYSTEM_FAIL);
        }
        pstMainCtrl->m_stEquipMgr.UpdatePotenLevel (stPlayerBaseInfo);
        pstMainCtrl->m_stPlayerBaseInfoHash[iIndex] = stPlayerBaseInfo;

        iIndex = pstMainCtrl->m_stPlayerDetailInfoHash.HashAlloc(stPlayerBaseInfo._uiGID);
        if (iIndex < 0)
        {
            CT_ERROR(("alloc fail"));
            return AnsClients(RET_SYSTEM_FAIL);
        }
        stPlayerDetailInfo._uiGID = stPlayerBaseInfo._uiGID;
        pstMainCtrl->m_stPlayerDetailInfoHash[iIndex] = stPlayerDetailInfo;        

        iIndex = pstMainCtrl->m_stPlayerDetailEx1InfoHash.HashAlloc(stPlayerBaseInfo._uiGID);
        if (iIndex < 0)
        {
            CT_ERROR(("m_stPlayerDetailEx1InfoHash alloc fail"));
            return AnsClients(RET_SYSTEM_FAIL);
        }
        stPlayerDetailInfoEx1._uiGID = stPlayerBaseInfo._uiGID;
        pstMainCtrl->m_stPlayerDetailEx1InfoHash[iIndex] = stPlayerDetailInfoEx1;

        iIndex = pstMainCtrl->m_stPlayerSnsDetailInfoHash.HashAlloc(stPlayerBaseInfo._uiGID);
        if (iIndex < 0)
        {
            CT_ERROR(("alloc fail"));
            return AnsClients(RET_SYSTEM_FAIL);
        }
        stPlayerSnsDetailInfo._uiGID = stPlayerBaseInfo._uiGID;
        stPlayerSnsDetailInfo._stMyInfo._uiGID = stPlayerBaseInfo._uiGID;
        stPlayerSnsDetailInfo._stCommInfo._uiGID = stPlayerBaseInfo._uiGID;
        stPlayerSnsDetailInfo._stCommInfo._sUserToken = stPlayerBaseInfo._sUserToken;
        pstMainCtrl->m_stPlayerSnsDetailInfoHash[iIndex] = stPlayerSnsDetailInfo;

        iIndex = pstMainCtrl->m_stUnactPartnerInfoHash.HashAlloc(stPlayerBaseInfo._uiGID);
        if (iIndex < 0)
        {
            CT_ERROR(("alloc fail"));
            return AnsClients(RET_SYSTEM_FAIL);
        }
        stPlayerUnactPartnerInfo._uiGID = stPlayerBaseInfo._uiGID;
        stPlayerUnactPartnerInfo._astListData.Clear();
        pstMainCtrl->m_stUnactPartnerInfoHash[iIndex]._uiGID = stPlayerBaseInfo._uiGID;
        pstMainCtrl->m_stUnactPartnerInfoHash[iIndex] = stPlayerUnactPartnerInfo;

        //token 存入hash
        iIndex = pstMainCtrl->m_stUserTokenToGID.HashAlloc(szUserToken);
        if (iIndex >= 0)
        {
            CGidList& stGidList = pstMainCtrl->m_stUserTokenToGID[iIndex];
            uiGID = stPlayerBaseInfo._uiGID;
            stGidList._auiGID.AddOneItem(uiGID);
        }
        else
        {
            CT_ERROR(("alloc fail"));
            return AnsClients(RET_SYS_USER_FULL);
        }

        iIndex = pstMainCtrl->m_stPlayerSnsCommInfoHash.HashAlloc(stPlayerBaseInfo._uiGID);
        if (iIndex >= 0)
        {
            pstMainCtrl->m_stPlayerSnsCommInfoHash[iIndex]._uiGID = stPlayerBaseInfo._uiGID;
        }
        else
        {
            CT_ERROR(("sns comm alloc fail"));
            return AnsClients(RET_SYS_USER_FULL);
        }

        iIndex = pstMainCtrl->m_stPlayerCacheDataHash.HashAlloc(stPlayerBaseInfo._uiGID);
        if (iIndex >= 0)
        {
            pstMainCtrl->m_stPlayerCacheDataHash[iIndex]._uiGID = stPlayerBaseInfo._uiGID;
        }
        else
        {
            CT_ERROR(("cache data alloc fail"));
            return AnsClients(RET_SYS_USER_FULL);
        }

        //返回GID
        stAns.set_gid(stPlayerBaseInfo._uiGID);
        return LogicDo(RET_OK);
    }
    else
    {
        bIsNewbie = false;
    }

    if (pstCmd->stAns.stResult.iResultID != RET_OK)
    {
        CT_ERROR((""));
        return AnsClients(pstCmd->stAns.stResult.iResultID);
    }

    int iIndex = pstMainCtrl->m_stUserTokenToGID.HashFind(szUserToken);
    if (iIndex < 0)
    {
        CT_ERROR((""));
        return AnsClients(RET_SYS_ERROR);
    }

    return LogicDo(RET_OK);
}

int CCmdLogin::LogicDo(int iRet)
{
    if (iRet != 0)
    {
        CT_ERROR(("CCmdLogin::LogicDo error %d", iRet));
        return AnsClients(iRet);
    }

    //多账号判断
    int iIndex = pstMainCtrl->m_stUserTokenToGID.HashFind(szUserToken);
    if (0 == stReq.use_gid() && iIndex >= 0)
    {
        CGidList& stGidList = pstMainCtrl->m_stUserTokenToGID[iIndex];
        if (stGidList._auiGID.Size() > 1) //有多个账号
        {
            int iValidCount = 0;
            unsigned int uiUseGID = 0;
            for (int i = 0; i < stGidList._auiGID.Size(); ++i) //尝试帮用户选择一个账号
            {
                if (pstMainCtrl->m_stCommConfigLoader._stZoneConfig.GetTencentZoneID(stReq.zone_id())
                    == (int)(stGidList._auiGID[i] / MAX_USER_PER_ZONE))
                {
                    //stReq.set_use_gid(stGidList._auiGID[i]);
                    iValidCount = 1;
                    uiUseGID = stGidList._auiGID[i];
                    break;
                }

                iIndex = pstMainCtrl->m_stPlayerSnsCommInfoHash.HashFind(stGidList._auiGID[i]);
                if (iIndex < 0)
                {
                    CT_WARNING(("gid %u not find", stGidList._auiGID[i]));
                    continue;
                }
                CPlayerSnsCommInfo& stPlayerSnsCommInfo = pstMainCtrl->m_stPlayerSnsCommInfoHash[iIndex];

                if (stPlayerSnsCommInfo._sRoleName.GetDataLen() == 0)
                {
                    continue;
                }

                iValidCount++;
                uiUseGID = stPlayerSnsCommInfo._uiGID;
            }

            if (iValidCount == 1)
            {
                stReq.set_use_gid(uiUseGID);
            }
            else if (iValidCount == 0)
            {
                stReq.set_use_gid(stGidList._auiGID[0]);
            }
        }
        else if (stGidList._auiGID.Size() == 1)
        {
            stReq.set_use_gid(stGidList._auiGID[0]);
        }
        else if (stGidList._auiGID.Size() == 0)
        {
            CT_ERROR(("CGidList no data %s", szUserToken()));
            return AnsClients(RET_SYS_ERROR);
        }

        if (0 == stReq.use_gid())
        {
            //让用户选择角色
            CCmdInnerUserLogin* pstCmd =
                (CCmdInnerUserLogin*)CT_CMDFACTORY->CreateCmd(
                    ID_MAIN_INNER_USER_LOGIN);
            if (!pstCmd)
            {
                CT_ERROR(("create CCmdInnerUserLogin error"));
                return Done(RET_SYS_NULL_POINTER);    
            }
            
            pstCmd->pstMainCtrl = CMainCtrl::m_pstMain;
            pstCmd->stMsgHead = stMsgHead;
            pstCmd->stEnpHead = stEnpHead;
            pstCmd->_bIsTencentLogin = bIsTencentLogin;
            pstCmd->_iZoneID = stReq.zone_id();
            pstCmd->_szUserToken = szUserToken;
            pstCmd->_stTencentApiKeyValue = stTencentApiKeyValue;
            
            pstCmd->Do(NULL);

            return Done(RET_OK);    
        }
    }
    
    if (bIsTencentLogin && !bIsCheckLogin)
    {
        bIsCheckLogin = true;

        //平台校验登录
        CCmdApi* pstCmd = (CCmdApi*)CT_CMDFACTORY->CreateCmd(ID_MAINAPI_TAPI);
        if (!pstCmd)
        {
            CT_ERROR(("create cmd error"));
            return AnsClients(RET_SYS_ERROR);
        }

        pstCmd->pstMainCtrl = CMainCtrl::m_pstMain;
        pstCmd->stReq._ucReqType = CReqApi::API_TENCENT;

        if (0 == strcmp(stReq.pf().c_str(), "3366"))
        {
            pstCmd->stReq._szTApiName.Set("/v3/user/is_login");
            pstCmd->stReq._stTApiKeyValue = stTencentApiKeyValue;
        }
        else
        {
            pstCmd->stReq._szTApiName.Set("/v3/user/is_area_login");
            pstCmd->stReq._stTApiKeyValue = stTencentApiKeyValue;
            pstCmd->stReq._stTApiKeyValue.SetValue("seqid", stReq.seqid().c_str());            
        }
#if 0
        //判断是否从任务集市过来的
        CTKeyValue stMarketPara;
        stMarketPara.ParseFromHttpParam(stReq.params().c_str(), stReq.params().length());

        if (0 == strcmp(stMarketPara.GetValue("app_user_source"), "marketV2"))
        {
        
        }

        vector<string> aryStringList;        
        CTStringUtils::SplitNoSkip (stReq.params(), "&", aryStringList);        
        vector<string>::iterator it = aryStringList.begin();
        while (it != aryStringList.end())
        {
            if (*it == "app_user_source=marketV2")
            {
                bIsFromMarket = true;                
            }
            else
            {
                string strName;
                string strValue;
                CTStringUtils::SplitIni (*it, strName, strValue, '=');
                if (strName == "app_contract_id")
                {
                    bIsCheckFromMarket = true;  //如果是用任务集市登陆的话,就不主动跟平台查询了
                    stTencentApiKeyValue.SetValue("app_contract_id", strValue.c_str());
                    uiMarketTaskId = pstMainCtrl->m_stMarketMgr.GetTaskId(strValue.c_str());                    
                    CT_TRACE(("app_contract_id %s", strValue.c_str()));
                }
            }

            it++;
        }
#endif
        CT_TRACE(("bIsCheckLogin"));
        RegisterChild(pstCmd, true);
        return pstCmd->Do(NULL);
    }

    if (bIsHttpCreateUser && !bIsCheckInitInfo)
    {
        bIsCheckInitInfo = true;

        iRet = CCmdInitUserInfo::CheckNewRoleName(szRoleName);
        if (iRet != RET_OK)
        {
            return AnsClients(iRet);
        }

        //在平台检查
        if (bIsTencentLogin)
        {
            CCmdApi* pstCmd = (CCmdApi*)CT_CMDFACTORY->CreateCmd(ID_MAINAPI_TAPI);
            if (!pstCmd)
            {
                CT_WARNING(("create cmd error"));
                return AnsClients(RET_SYS_ERROR);
            }

            pstCmd->pstMainCtrl = pstMainCtrl;
            pstCmd->stReq._ucReqType = CReqApi::API_TENCENT;
            pstCmd->stReq._szTApiName.Set("/v3/csec/word_filter");
            pstCmd->stReq._stTApiKeyValue = stTencentApiKeyValue;
            pstCmd->stReq._stTApiKeyValue.SetValue("content", szRoleName());

            uint64 u64MsgID = CT_UINT64_MAKE(pstMainCtrl->m_stNowTime.tv_usec, pstMainCtrl->m_stNowTime.tv_sec);
            pstCmd->stReq._stTApiKeyValue.SetValue("msgid", CTStringUtils::Uint64ToString(u64MsgID, 16));

            CT_TRACE(("bIsCheckInitInfo"));
            RegisterChild(pstCmd, true);
            return pstCmd->Do(NULL);
        } 
    }
    else if (bIsCheckInitInfo && m_pstChild && ID_MAINAPI_TAPI == m_pstChild->GetCmdID())
    {
        CCmdApi* pstCmd = (CCmdApi*)m_pstChild;
        if (pstCmd->stReq._szTApiName == "/v3/csec/word_filter")
        {
            if (atoi(pstCmd->stAns._stTApiKeyValue.GetValue("is_dirty")) != 0)
            {
                return AnsClients(ERROR_HAS_SEN_WORD);
            }
        }
    }

    if (!bIsCheckInvited && stReq.has_invkey() && stReq.has_iopenid() && stReq.has_itime()
        && strlen(stReq.invkey().c_str()) > 0 && strlen(stReq.iopenid().c_str()) > 0
        && strlen(stReq.itime().c_str()) > 0)
    {
        if (stReq.has_open_id())
        {
            CT_TRACE(("QQFriend: openid(%s) invkey(%s) iopenid(%s) itime(%s)",
                stReq.open_id().c_str(),stReq.invkey().c_str(),
                stReq.iopenid().c_str(),stReq.itime().c_str()));
        }
        else
        {
            CT_TRACE(("QQFriend: openid(null) invkey(%s) iopenid(%s) itime(%s)",
                stReq.invkey().c_str(),stReq.iopenid().c_str(),
                stReq.itime().c_str()));
        }

        bIsCheckInvited = true;

        //平台校验邀请者信息
        CCmdApi* pstCmd = (CCmdApi*)CT_CMDFACTORY->CreateCmd(ID_MAINAPI_TAPI);
        if (!pstCmd)
        {
            CT_ERROR(("create cmd error"));
            return AnsClients(RET_SYS_ERROR);
        }

        pstCmd->pstMainCtrl = CMainCtrl::m_pstMain;
        pstCmd->stReq._ucReqType = CReqApi::API_TENCENT;
        pstCmd->stReq._szTApiName.Set("/v3/spread/verify_invkey");
        pstCmd->stReq._stTApiKeyValue = stTencentApiKeyValue;
        pstCmd->stReq._stTApiKeyValue.SetValue("invkey", stReq.invkey().c_str());
        pstCmd->stReq._stTApiKeyValue.SetValue("itime", stReq.itime().c_str());
        pstCmd->stReq._stTApiKeyValue.SetValue("iopenid", stReq.iopenid().c_str());
        
        CT_TRACE(("bIsCheckInvited"));
        RegisterChild(pstCmd, true);
        return pstCmd->Do(NULL);
    }
    else if (bIsCheckInvited && m_pstChild && ID_MAINAPI_TAPI == m_pstChild->GetCmdID())
    {
        CCmdApi* pstCmd = (CCmdApi*)m_pstChild;
        if (pstCmd->stReq._szTApiName == "/v3/spread/verify_invkey")
        {
            if (atoi(pstCmd->stAns._stTApiKeyValue.GetValue("is_right")) == 1)
            {
                bHasInvitedInfo = true;
            }
            else
            {
                bHasInvitedInfo = false;
            }

            if (stReq.has_open_id())
            {
                CT_TRACE(("QQFriend: openid(%s) bHasInviteInfo(%d)",
                    stReq.open_id().c_str(),bHasInvitedInfo));
            }
            else
            {
                CT_TRACE(("QQFriend: openid(null) bHasInviteInfo(%d)",
                    bHasInvitedInfo));
            }
        }
    }

    //检查用户是否存在
    iIndex = pstMainCtrl->m_stUserTokenToGID.HashFind(szUserToken);
    if (iIndex >= 0)
    {
        CGidList& stGidList = pstMainCtrl->m_stUserTokenToGID[iIndex];

        if (stGidList._auiGID.Size() == 0)
        {
            CT_ERROR(("%s", szUserToken()));
            return AnsClients(RET_SYS_ERROR);
        }

        if (stGidList._auiGID.Size() > 1) //存在多个帐号
        {
            unsigned int uiUseGID = 0;

            //判断是否可根据大区选择
            if (bIsTencentLogin)
            {
                for (int i = 0; i < stGidList._auiGID.Size(); ++i)
                {
                    if (pstMainCtrl->m_stCommConfigLoader._stZoneConfig.GetTencentZoneID(stReq.zone_id())
                        == (int)(stGidList._auiGID[i] / MAX_USER_PER_ZONE))
                    {
                        stReq.set_use_gid(stGidList._auiGID[i]);
                        break;
                    }
                }
            }

            if (stReq.use_gid() == 0) //还未选择帐号
            {
                //返回角色列表

                int iValidAccountCount = 0; //可选择的帐号数量
                for (int i = 0; i < stGidList._auiGID.Size(); ++i)
                {
                    //返回列表
                    int iIndex = pstMainCtrl->m_stPlayerSnsCommInfoHash.HashFind(stGidList._auiGID[i]);
                    if (iIndex < 0)
                    {
                       CT_WARNING(("gid %u not find", stGidList._auiGID[i]));
                       continue;
                    }
                    CPlayerSnsCommInfo& stPlayerSnsCommInfo = pstMainCtrl->m_stPlayerSnsCommInfoHash[iIndex];

                    if (stPlayerSnsCommInfo._sRoleName.GetDataLen() == 0)
                    {
                        continue;
                    }

                    uiUseGID = stPlayerSnsCommInfo._uiGID;
                    
                    MsgMultiAccountInfo* pstMsgMultiAccountInfo = stAns.add_multi_account();
                    pstMsgMultiAccountInfo->set_gid(stPlayerSnsCommInfo._uiGID);
                    pstMsgMultiAccountInfo->set_rolename(stPlayerSnsCommInfo._sRoleName());
                    pstMsgMultiAccountInfo->set_career(stPlayerSnsCommInfo._ucCareer);
                    pstMsgMultiAccountInfo->set_level(stPlayerSnsCommInfo._usLevel);
                    pstMsgMultiAccountInfo->set_sex(stPlayerSnsCommInfo._ucIsMale);

                    iValidAccountCount++;
                }

                if (iValidAccountCount > 1)
                {
                    return AnsClients(RET_OK);
                }

                if (iValidAccountCount == 0)
                {
                    uiUseGID = stGidList._auiGID[0]; //默认选第一个
                }
                
            }
            else
            {
                uiUseGID = stReq.use_gid();
            }

            //检查uiUseGID是否有效
            int iIndex = pstMainCtrl->m_stPlayerSnsCommInfoHash.HashFind(uiUseGID);
            if (iIndex < 0)
            {
                CT_WARNING(("gid %u not find", uiUseGID));
                return AnsClients(RET_SYS_ERROR);
            }
            CPlayerSnsCommInfo& stPlayerSnsCommInfo = pstMainCtrl->m_stPlayerSnsCommInfoHash[iIndex];

#ifndef _DEBUG
            if (!(stPlayerSnsCommInfo._sUserToken == szUserToken))
            {
                CT_ERROR((""));
                return AnsClients(RET_SYS_ERROR);
            }    
#endif 
            CT_TRACE(("UserToken is %s", stPlayerSnsCommInfo._sUserToken()));

            uiGID = uiUseGID;
            stGidList._uiNowUseGID = uiGID;
        }
        else
        {
            uiGID = stGidList._auiGID[0];
            stGidList._uiNowUseGID = uiGID;
        }
    }
    else if (bIsHttpCreateUser)
    {
        //查询dbsvr
        CCmdSelectDataFromDBSvr* pstCmd = (CCmdSelectDataFromDBSvr*)CT_CMDFACTORY->CreateCmd(ID_MAINDB_SELECTDATA);
        if (!pstCmd)
        {
            CT_WARNING(("create cmd error"));
            return AnsClients(RET_SYSTEM_FAIL);
        }

        pstCmd->pstMainCtrl = pstMainCtrl;
        pstCmd->stReq.m_ucCheckUpdateMgr = 0;
        pstCmd->stReq.m_stKey.m_chDataType = DT_PLAYER_GID;
        pstCmd->stReq.m_stKey.m_sStrID.Set("%s", szUserToken());

        RegisterChild(pstCmd);

        return pstCmd->Do(NULL);
    }

    stAns.set_gid(uiGID);
    PREPARE_PLAYER_BASE_INFO(this, uiGID);
    ASSERT_PLAYER_PREPARED(uiGID);

    PREPARE_PLAYER_DETAIL_INFO(this, uiGID);
    ASSERT_PLAYER_DETAIL_PREPARED(uiGID);

    PREPARE_PLAYER_DETAIL_EX1_INFO(this, uiGID);
    ASSERT_PLAYER_DETAIL_EX1_INFO(uiGID);

    PREPARE_PLAYER_SNS_DETAIL_INFO(this, uiGID);
    PREPARE_UNACT_PARTNER_INFO(this, uiGID);

    iIndex = pstMainCtrl->m_stPlayerBaseInfoHash.HashFind(uiGID);
    if (iIndex < 0)
    {
        CT_ERROR((""));
        return AnsClients(RET_NO_USER);
    }
    CPlayerBaseInfo& stPlayerBaseInfo = pstMainCtrl->m_stPlayerBaseInfoHash[iIndex];
    
    if (pstMainCtrl->m_iNow < stPlayerBaseInfo._stFreezeData._iLoginLimit)
    {
        CT_ERROR((""));
        return AnsClients(ERROR_LOGIN_LIMIT);
    }
    
    iIndex = pstMainCtrl->m_stPlayerDetailInfoHash.HashFind(uiGID);
    if (iIndex < 0)
    {
        CT_ERROR((""));
        return AnsClients(RET_NO_USER);
    }
    CPlayerDetailInfo& stPlayerDetailInfo = pstMainCtrl->m_stPlayerDetailInfoHash[iIndex];

    iIndex = pstMainCtrl->m_stPlayerDetailEx1InfoHash.HashFind(uiGID);
    if (iIndex < 0)
    {
        CT_ERROR((""));
        return AnsClients(RET_NO_USER);
    }
    CPlayerDetailInfoEx1 & stPlayerDetailInfoEx1 = pstMainCtrl->m_stPlayerDetailEx1InfoHash[iIndex];

    iIndex = pstMainCtrl->m_stPlayerSnsDetailInfoHash.HashFind(uiGID);
    if (iIndex < 0)
    {
        CT_ERROR((""));
        return AnsClients(RET_NO_USER);
    }
    CPlayerSnsDetailInfo& stPlayerSnsDetailInfo = pstMainCtrl->m_stPlayerSnsDetailInfoHash[iIndex];

    iIndex = pstMainCtrl->m_stUnactPartnerInfoHash.HashFind(uiGID);
    if (iIndex < 0)
    {
        CT_ERROR((""));
        return AnsClients(RET_NO_USER);
    }
    CUnactPartnerInfo& stUnactPartnerInfo = pstMainCtrl->m_stUnactPartnerInfoHash[iIndex];

#if 0
    if (false == stPlayerDetailInfoEx1._stMarketTask.NeedCheckStatus())
    {
        bIsCheckFromMarket = false;
    }
    
    //检查集市登陆
    if (true == bIsCheckFromMarket)
    {
        pstMainCtrl->m_stMarketMgr.CheckTaskStatus(this, stPlayerDetailInfoEx1._stMarketTask, uiGID, stTencentApiKeyValue);
        bIsCheckFromMarket = false;
        return RET_OK;
    }else if ((false == bIsCheckFromMarket) && m_pstChild && ID_MAINAPI_TAPI == m_pstChild->GetCmdID())
    {
        CCmdApi* pstCmd = (CCmdApi*)m_pstChild;
        if (pstCmd->stReq._szTApiName == "/v3/pay/check_task_status")
        {
            stTencentApiKeyValue.SetValue("app_contract_id", pstCmd->stAns._stTApiKeyValue.GetValue("app_contract_id"));
            uiMarketTaskId = pstMainCtrl->m_stMarketMgr.GetTaskId(stTencentApiKeyValue.GetValue("app_contract_id"));
            CT_TRACE(("app_contract_id %s, %d", pstCmd->stAns._stTApiKeyValue.GetValue("app_contract_id"), uiMarketTaskId));
        }
    }
#endif

    //设置登录
    //踢掉已有的用户
    bool bDualLogin = false;
    if (pstMainCtrl->m_stPlayerOnline.CheckOnline(stPlayerBaseInfo._uiGID))
    {
        CEnpNetHead stNetHandle;
        pstMainCtrl->m_stPlayerOnline.GetOnlinePlayerHandle(stPlayerBaseInfo._uiGID, stNetHandle);

        if (stNetHandle.uiHandle == stEnpHead.uiHandle)
        {
            //不允许一个号重复发登录
            //CT_ERROR(("CCmdLogin::LogicDo %u, %s", stPlayerBaseInfo._uiGID, szUserToken()));
            //return AnsClients(ERROR_HAS_LOGIN);
            CT_ERROR(("CCmdLogin::LogicDo dual login %u, %s", stPlayerBaseInfo._uiGID, szUserToken()));
            bDualLogin = true;
        }
        else
        {
            //发送消息
            PBMsgHead stTipMsgHead = stMsgHead;
            stTipMsgHead.set_msgid(ID_MAIN_TIPS);
            stTipMsgHead.set_msgtype(CSMsgDef::EMT_ANSWER);
            stTipMsgHead.set_msgact(0);

            MsgTips stTips;
            stTips.set_type(5);

            pstMainCtrl->m_stEncodeBuf.Clear();
            pstMainCtrl->EncodePBMsg(stTipMsgHead, pstMainCtrl->m_stEncodeBuf);
            pstMainCtrl->EncodePBMsg(stTips, pstMainCtrl->m_stEncodeBuf);
            pstMainCtrl->AnswerToClient(stNetHandle, pstMainCtrl->m_stEncodeBuf, true);

            //设置离线
            pstMainCtrl->SetOffline(stPlayerBaseInfo._uiGID, stNetHandle);
        }

    }

    //防沉迷
    stPlayerBaseInfo._iDefendValidInfo = 1;
    //Defend check -----------end

    CPlatformInfo stPlatformInfo;
    stPlatformInfo._bIsTencentLogin = bIsTencentLogin;
    stPlatformInfo._stTencentApiKeyValue = stTencentApiKeyValue;
    stPlatformInfo._iLastCheckLoginTime = pstMainCtrl->m_iNow;

    //更新公告
    CZoneConfigData stZoneConfigData;
    pstMainCtrl->m_stCommConfigLoader._stZoneConfig.GetZoneConfig(CONF->ZoneID, stZoneConfigData);
    if (stPlayerSnsDetailInfo._stMyInfo._stPlayerOssInfo._iLastLoginTime < stZoneConfigData._iLastReleaseTime)
    {
        //发送更新公告
        PBMsgHead  stMsgHead;
        stMsgHead.set_msgid(ID_MAIN_TIPS);
        stMsgHead.set_msgtype(CSMsgDef::EMT_ANSWER);

        MsgTips stAns;
        stAns.set_type(65);

        pstMainCtrl->m_stEncodeBuf.Clear();
        pstMainCtrl->EncodePBMsg(stMsgHead, pstMainCtrl->m_stEncodeBuf);
        pstMainCtrl->EncodePBMsg(stAns, pstMainCtrl->m_stEncodeBuf);
        pstMainCtrl->AnswerToClient(stEnpHead, pstMainCtrl->m_stEncodeBuf);
    }
    
    if (!bDualLogin)
    {
        pstMainCtrl->SetOnline(stPlayerBaseInfo._uiGID, stEnpHead, stPlatformInfo);
        stPlayerSnsDetailInfo._stCommInfo._iLastLogInTime = pstMainCtrl->m_iNow;
        CT_TRACE(("stPlayerSnsDetailInfo._stCommInfo._iLastLogInTime=%d", stPlayerSnsDetailInfo._stCommInfo._iLastLogInTime));
    }

    iIndex = pstMainCtrl->m_stPlayerOnlineDataHash.HashFind(stPlayerBaseInfo._uiGID);
    if (iIndex < 0)
    {
        CT_ERROR(("user %u not in m_stPlayerOnlineDataHash", stPlayerBaseInfo._uiGID));
        pstMainCtrl->SetOffline(stPlayerBaseInfo._uiGID, stEnpHead);
        return AnsClients(RET_SYSTEM_FAIL);
    }
    CPlayerOnlineData& stPlayerOnlineData = pstMainCtrl->m_stPlayerOnlineDataHash[iIndex];

    //初始化平台参数
    stPlayerOnlineData._bIsTencentLogin = bIsTencentLogin;
    stPlayerOnlineData._stTencentApiKeyValue = stTencentApiKeyValue;
    
    //qzone：空间；pengyou：朋友；qplus：Q+；tapp：微博；qqgame：QQGame；3366：3366；kapp：开心
    if (0 == strcmp(stTencentApiKeyValue.GetValue("pf"), "qzone"))
    {
        stPlayerOnlineData._ucTencentLoginFrom = TENCENT_LOGIN_FROM_QZONE;
    }
    else if (0 == strcmp(stTencentApiKeyValue.GetValue("pf"), "pengyou"))
    {
        stPlayerOnlineData._ucTencentLoginFrom = TENCENT_LOGIN_FROM_PENGYOU;
    }
    else if (0 == strcmp(stTencentApiKeyValue.GetValue("pf"), "qqgame"))
    {
        stPlayerOnlineData._ucTencentLoginFrom = TENCENT_LOGIN_FROM_QQGAME;
    }
    else if (0 == strcmp(stTencentApiKeyValue.GetValue("pf"), "3366"))
    {
        stPlayerOnlineData._ucTencentLoginFrom = TENCENT_LOGIN_FROM_3366;
    }
    else
    {
        stPlayerOnlineData._ucTencentLoginFrom = TENCENT_LOGIN_FROM_UNKNOWEN;
    }

    //防沉迷信息
    stPlayerOnlineData._iLoginTime = stPlayerSnsDetailInfo._stCommInfo._iLastLogInTime;
    stPlayerOnlineData._iDefendValidInfo = stPlayerBaseInfo._iDefendValidInfo;
    stPlayerOnlineData._iDefTotalOnlineTime = stPlayerBaseInfo._iDefTotalOnlineTime;

    if (!bIsNewbie)
    {   
        if (stPlayerBaseInfo._ucIsInited == 1)
        {
            iRet = stPlayerOnlineData.InitData(stAns.gid(), stPlayerBaseInfo, stPlayerDetailInfo, stPlayerDetailInfoEx1, stPlayerSnsDetailInfo);
            if (RET_OK != iRet)
            {
                CT_ERROR((""));
                return AnsClients(iRet);
            }

            pstMainCtrl->FindPlayerCacheData(stPlayerBaseInfo._uiGID);

            //进入场景
            iRet = pstMainCtrl->m_stMapViews.IntoMap(stPlayerOnlineData._uiNowMapID, stPlayerBaseInfo._uiGID, false,
                stPlayerBaseInfo._usXPos, stPlayerBaseInfo._usYPos);
            if (iRet != 0)
            {
                CT_ERROR((""));
                return AnsClients(iRet);
            }

            pstMainCtrl->m_stRoleMgr.UpdateLoginDays(stPlayerDetailInfoEx1, pstMainCtrl->m_iNow);
        }
        else //为了在初始化角色时做任务
        {
            stPlayerOnlineData._stUserTask.Clean();
            stPlayerOnlineData._stUserTask.SetUserGid( stAns.gid() );
            //初始化任务
            iRet = stPlayerOnlineData._stUserTask.Init(stPlayerBaseInfo._stUserTaskData);
            if (iRet != 0)
            {
                CT_ERROR((""));
                return AnsClients(iRet);
            }
        }

        stPlayerOnlineData._stUserTask.SetMarketTaskID(stPlayerDetailInfoEx1._stMarketTask._uiTaskId);
    }
    else
    {
        //基础数据
        stPlayerBaseInfo._shLevel = 1;
        stPlayerBaseInfo._i64NowExp = 0;
        stPlayerBaseInfo._i64Silver = 0;
        stPlayerSnsDetailInfo._stCommInfo._usLevel = stPlayerBaseInfo._shLevel;
        stPlayerSnsDetailInfo._stCommInfo._sUserToken = stPlayerBaseInfo._sUserToken;

        //初始场景
        stPlayerBaseInfo._uiMapID = 102;
        stPlayerBaseInfo._usXPos = 0xFFFF;
        stPlayerBaseInfo._usYPos = 0xFFFF;

        //接第一个任务 //任务需要的人物初始化之前被初始化，因为初始化人物过程中需要做任务
        stPlayerOnlineData._stUserTask.Clean();
        stPlayerOnlineData._stUserTask.SetUserGid( stAns.gid() );
                
        CTaskID stFirstAccTask;
        stFirstAccTask._uiBranchID = 0;
        stFirstAccTask._uiTaskID = TASK_FIRST_TASK_ID;
        pstMainCtrl->m_stTaskMgr.AcceptTask(stFirstAccTask, stPlayerOnlineData._stUserTask);
        stPlayerOnlineData._stUserTask.GetData(stPlayerBaseInfo._stUserTaskData);

        if (bIsFromMarket)
        {
            //接受任务集市任务
            stPlayerDetailInfoEx1._stMarketTask._ucIsFromMarket = true;
            stPlayerDetailInfoEx1._stMarketTask._uiTaskId = uiMarketTaskId;
            pstMainCtrl->m_stMarketMgr.AcceptTask (stPlayerDetailInfoEx1._stMarketTask, stPlayerOnlineData);
        }


        //更新登陆的登录天数
        pstMainCtrl->m_stRoleMgr.UpdateLoginDays(stPlayerDetailInfoEx1, pstMainCtrl->m_iNow);
#ifdef _DEBUG
        stPlayerBaseInfo._iGold = 10000;
        stPlayerBaseInfo._chVipLevel = 0;
#endif

        //QQ好友邀请
        if (bHasInvitedInfo && stReq.has_iopenid())
        {
            CCmdInnerQQFriend* pstCmdTmp =
                (CCmdInnerQQFriend*)CT_CMDFACTORY->CreateCmd(
                    ID_MAIN_INNER_QQ_FRIEND);
            if (pstCmdTmp)
            {
                pstCmdTmp->pstMainCtrl = CMainCtrl::m_pstMain;
                pstCmdTmp->_uiGID = stPlayerBaseInfo._uiGID;
                pstCmdTmp->_iSubCmd =
                    CFriendMgr::CMD_QQ_FRIEND_SUB_PREPARE_TOKEN_GID;
                pstCmdTmp->_iValue = 0;
                pstCmdTmp->_uiValue = 0;
                pstCmdTmp->_szInviterToken.Set("%s",stReq.iopenid().c_str());
                pstCmdTmp->Do(NULL);
            }
            else
            {
                CT_WARNING(("create CCmdInnerQQFriend error"));
            }
        }
    }

    //
    unsigned int uiNotifyType = NOTIFY_SYSOPEN_INFO;
    pstMainCtrl->m_stNotifyMgr.Notify(stPlayerBaseInfo._uiGID, uiNotifyType);

    //上线通知
    PBMsgHead stTipMsgHead = stMsgHead;
    stTipMsgHead.set_msgid(ID_MAIN_TIPS);
    stTipMsgHead.set_msgtype(CSMsgDef::EMT_ANSWER);
    stTipMsgHead.set_msgact(0);

    MsgTips stTips;
    stTips.set_type(2);
    stTips.set_dest_gid(stPlayerBaseInfo._uiGID);

    pstMainCtrl->m_stEncodeBuf.Clear();
    pstMainCtrl->EncodePBMsg(stTipMsgHead, pstMainCtrl->m_stEncodeBuf);
    pstMainCtrl->EncodePBMsg(stTips, pstMainCtrl->m_stEncodeBuf);

    CTArray<unsigned int, MAX_PLAYER_ONLINE> astGIDArray;
    pstMainCtrl->m_stPlayerOnline.GetAllOnlineUser(astGIDArray);
    for (int i = 0; i < astGIDArray.Size(); ++i)
    {
        pstMainCtrl->NotifyOnlineUser(astGIDArray[i], pstMainCtrl->m_stEncodeBuf);
    }

    //发送离线消息
    COfflineTips stOfflineTips = stPlayerSnsDetailInfo._stMyInfo._stOfflineTips;

    //发送竞技场离线消息
    if (stPlayerDetailInfo._stUserArenaData._iBeenAtkDropToRank > 0)
    {
        CTips stTips;
        stTips._iType = 15;
        stTips._iData1 = (int)stPlayerDetailInfo._stUserArenaData._iBeenAtkGID;
        stTips._iData2 = stPlayerDetailInfo._stUserArenaData._iBeenAtkDropToRank;

        stOfflineTips.AddTips(stTips);

        stPlayerDetailInfo._stUserArenaData._iBeenAtkDropToRank = 0;
    }

    //发送精力系统离线消息
    if (pstMainCtrl->m_stCommConfigLoader.IsOpen(SYS_OPEN_COND_ID_34, stPlayerBaseInfo, stPlayerOnlineData))
    {
        CUserEnergy& stUserEnergy = stPlayerBaseInfo._stUserEnergy;
        if (stUserEnergy.IsMealTime(pstMainCtrl->m_iNow))
        {
            int iMealSeq = 0;
            stUserEnergy.GetMealSeq(pstMainCtrl->m_iNow, iMealSeq);

            if (stUserEnergy._iLastMealSeq != iMealSeq
                || pstMainCtrl->m_stEnergyMgr.CanOpenMeal(stUserEnergy))
            {
                CTips stTips;
                if (stUserEnergy.IsLunch(iMealSeq))
                {
                    stTips._iType = 16;
                    stOfflineTips.AddTips(stTips);
                }
                else if (stUserEnergy.IsDinner(iMealSeq))
                {
                    stTips._iType = 17;
                    stOfflineTips.AddTips(stTips);
                }
            }
        }
    }

    //登录奖励
    bool bUpdate = false;
    pstMainCtrl->m_stLoginRewardMgr.UpdateData(stPlayerDetailInfoEx1, bUpdate);

    //发送拍卖会上线金钱返还和离线消息
    pstMainCtrl->m_stAuctionMgr.CheckBackMoneyOnLogin(stPlayerBaseInfo);

    //排行榜第一名登陆时,发送跑马灯
    pstMainCtrl->m_stRankMgr.CheckWhenLogIn(uiGID, stPlayerSnsDetailInfo._stCommInfo._stTitle);

    //商城中新物品的提示
    pstMainCtrl->m_stQQMallMgr.CheckAndSendTips(uiGID);
    
    //发送离线消息
    stPlayerSnsDetailInfo._stMyInfo._stOfflineTips.Clear();
    pstMainCtrl->SendTips(stPlayerBaseInfo._uiGID, stOfflineTips);

    //发送已开启的活动
    pstMainCtrl->m_stActMgr.NotifyActListToRole(stPlayerBaseInfo, stPlayerDetailInfo);

    //奖励找回更新初始时间
    pstMainCtrl->m_stRewardBackMgr.UpdateOpenZeroTime(stPlayerBaseInfo,
        stPlayerDetailInfoEx1, CRewardBackMgr::ENM_REWARD_BACK_STAT_LOGIN);

    if (!bDualLogin)
    {
        //登录账单
        pstMainCtrl->m_stOssMgr.TriggerLogin(stPlayerBaseInfo, stPlayerDetailInfo);
    }
    
    //保存数据
    CVarObjectKey stKey;
    stKey.m_chDataType = DT_PLAYER_BASE_INFO;
    stKey.m_u64ID = stPlayerBaseInfo._uiGID;
    pstMainCtrl->UpdateData(stKey, stPlayerBaseInfo, bIsNewbie ? VOP_CREATE : VOP_UPDATE);

    stKey.m_chDataType = DT_PLAYER_DETAIL_INFO;
    stKey.m_u64ID = stPlayerDetailInfo._uiGID;
    pstMainCtrl->UpdateData(stKey, stPlayerDetailInfo, bIsNewbie ? VOP_CREATE : VOP_UPDATE);

    stKey.m_chDataType = DT_PLAYER_DETAIL_EX1_INFO;
    stKey.m_u64ID = stPlayerDetailInfoEx1._uiGID;
    pstMainCtrl->UpdateData(stKey, stPlayerDetailInfoEx1, bIsNewbie ? VOP_CREATE : VOP_UPDATE);

    stKey.m_chDataType = DT_PLAYER_SNS_DETAIL_INFO;
    stKey.m_u64ID = stPlayerSnsDetailInfo._uiGID;
    pstMainCtrl->UpdateData(stKey, stPlayerSnsDetailInfo, bIsNewbie ? VOP_CREATE : VOP_UPDATE);

    stKey.m_chDataType = DT_PLAYER_UNACT_PARTNER;
    stKey.m_u64ID = stUnactPartnerInfo._uiGID;
    pstMainCtrl->UpdateData(stKey, stUnactPartnerInfo, bIsNewbie ? VOP_CREATE : VOP_UPDATE);

    return AnsClients(RET_OK);
}

int CCmdLogin::AnsClients(int iRet)
{
    pstMainCtrl->m_stEncodeBuf.Clear();

    if (RET_OK != iRet)
    {
        CT_ERROR(("CCmdLogin::LogicDo OPENID %s error %d", szUserToken(), iRet));
    }

    if (bIsHttpCreateUser)
    {
        return Done(iRet);
    }

    stMsgHead.set_msgret(iRet);
    stMsgHead.set_msgtype(CSMsgDef::EMT_ANSWER);

    if (iRet != RET_OK)
    {
        pstMainCtrl->ReturnMsgHead(stMsgHead, stEnpHead);
        return Done(iRet);
    }

    pstMainCtrl->EncodePBMsg(stMsgHead, pstMainCtrl->m_stEncodeBuf);
    pstMainCtrl->EncodePBMsg(stAns, pstMainCtrl->m_stEncodeBuf);

    if (pstMainCtrl->AnswerToClient(stEnpHead, pstMainCtrl->m_stEncodeBuf, true))
    {
        CT_WARNING((""));
        return Done(RET_SYS_ERROR);
    }

    return Done(iRet);
}

//////////////////////////////////////////////////////////////////////////
CT_REGISTER_ASYNCCMD(ID_MAIN_GET_USER_INFO , CCmdGetUserInfo);

CCmdGetUserInfo::CCmdGetUserInfo()
:bHasGetTencentUserInfo(false), bHasGetYellowInfo(false), bIsYellow(false)
{

}

int CCmdGetUserInfo::Do(void* pData)
{
    CT_ASSERT(pData);

    //解析消息
    CCmdPBDoParam* pstParam = (CCmdPBDoParam*) pData;
    pstMainCtrl = (CMainCtrl*) pstParam->m_pMain;

    if (pstParam->m_pstMsgHead->msgid() != ID_MAIN_GET_USER_INFO ||
        pstParam->m_pstMsgHead->msgtype() != CSMsgDef::EMT_REQUEST)
    {
        CT_ERROR(("Cmd Stat Err Cmd=%d CmdID=%d Tpye=%d",
            ID_MAIN_GET_USER_INFO,
            pstParam->m_pstMsgHead->msgid(),
            pstParam->m_pstMsgHead->msgtype()));
        return Done(RET_SYS_ERROR);
    }

    stMsgHead = *(pstParam->m_pstMsgHead);
    stEnpHead = *(pstParam->m_pstEnpHead);
    int iRet = pstMainCtrl->DecodePBMsg(stReq, pstParam);
    if (iRet)
    {
        return AnsClients(iRet);
    }
    //消息解析结束

    //检查登录
    uiGID = stReq.gid();
    iRet = pstMainCtrl->CheckLogin(uiGID, stEnpHead);
    if (iRet != RET_OK)
    {
        return AnsClients(iRet);
    }

#ifdef _DEBUG
    bIsYellow = true;
    bIsBlue = true;
#endif

    LogicDo(RET_OK);
    return RET_OK;
}

int CCmdGetUserInfo::LogicDo(int iRet)
{
    if (iRet != RET_OK)
    {
        if (iRet == RET_NO_RECORDER)
        {
            return AnsClients(RET_NO_USER);
        }

        return AnsClients(iRet);
    }

    unsigned int uiGID = stReq.gid();

    PREPARE_PLAYER_BASE_INFO(this, uiGID);
    ASSERT_PLAYER_PREPARED(uiGID);

    PREPARE_PLAYER_DETAIL_INFO(this, uiGID);
    ASSERT_PLAYER_DETAIL_PREPARED(uiGID);

    PREPARE_PLAYER_DETAIL_EX1_INFO (this, uiGID);

    PREPARE_PLAYER_ONLINE_DATA(this, stReq.gid());

    int iIndex = pstMainCtrl->m_stPlayerOnlineDataHash.HashFind(uiGID);
    if (iIndex < 0)
    {
        return AnsClients(RET_NO_USER);
    }
    CPlayerOnlineData& stPlayerOnlineData = pstMainCtrl->m_stPlayerOnlineDataHash[iIndex];

    //解析平台信息
    if (m_pstChild && ID_MAINAPI_TAPI == m_pstChild->GetCmdID())
    {
        CCmdApi* pstCmd = (CCmdApi*)m_pstChild;
        if (pstCmd->stReq._szTApiName == "/v3/user/get_info")
        {
            MsgTencentInfo* pstMsgTencentInfo = stAns.mutable_tencent_info();

            if (TENCENT_LOGIN_FROM_QQGAME == stPlayerOnlineData._ucTencentLoginFrom
                || TENCENT_LOGIN_FROM_3366 == stPlayerOnlineData._ucTencentLoginFrom)
            {
                //蓝钻
                pstMsgTencentInfo->set_is_blue_vip(pstCmd->stAns._stTApiKeyValue.GetValue("is_blue_vip"));
                pstMsgTencentInfo->set_is_blue_year_vip(pstCmd->stAns._stTApiKeyValue.GetValue("is_blue_year_vip"));
                pstMsgTencentInfo->set_blue_vip_level(pstCmd->stAns._stTApiKeyValue.GetValue("blue_vip_level"));
                pstMsgTencentInfo->set_is_super_blue_vip(pstCmd->stAns._stTApiKeyValue.GetValue("is_super_blue_vip"));

                if (pstMsgTencentInfo->is_blue_vip() != "0")
                {
                    bIsBlue = true;
                }
                else
                {
                    bIsBlue = false;
                }
            }

            if (TENCENT_LOGIN_FROM_3366 == stPlayerOnlineData._ucTencentLoginFrom)
            {
                //3366
                pstMsgTencentInfo->set_p3366_level(pstCmd->stAns._stTApiKeyValue.GetValue("3366_level"));
                pstMsgTencentInfo->set_p3366_level_name(pstCmd->stAns._stTApiKeyValue.GetValue("3366_level_name"));
                pstMsgTencentInfo->set_p3366_grow_level(pstCmd->stAns._stTApiKeyValue.GetValue("3366_grow_level"));
                pstMsgTencentInfo->set_p3366_grow_value(pstCmd->stAns._stTApiKeyValue.GetValue("3366_grow_value"));
            }

            pstMsgTencentInfo->set_sex(pstCmd->stAns._stTApiKeyValue.GetValue("gender"));

            //过滤单字节符号
            string s;
            for (int i = 0; i < (int)strlen(pstCmd->stAns._stTApiKeyValue.GetValue("nickname")); ++i)
            {
                char c = pstCmd->stAns._stTApiKeyValue.GetValue("nickname")[i];
                if (c < 0 
                    || (c >= 48 && c <= 57)     //数字
                    || (c >= 65 && c <= 90)     //大写字母
                    || (c >= 97 && c <= 122))   //小写字母
                {
                    s += c;
                }
            }
            
            pstMsgTencentInfo->set_qq_name(s);
        }
        else if (pstCmd->stReq._szTApiName == "/v3/user/is_vip")
        {
            MsgTencentInfo* pstMsgTencentInfo = stAns.mutable_tencent_info();

            if (TENCENT_LOGIN_FROM_PENGYOU == stPlayerOnlineData._ucTencentLoginFrom
                || TENCENT_LOGIN_FROM_QZONE == stPlayerOnlineData._ucTencentLoginFrom)
            {
                pstMsgTencentInfo->set_is_yellow_vip(pstCmd->stAns._stTApiKeyValue.GetValue("is_yellow_vip"));
                pstMsgTencentInfo->set_is_yellow_year_vip(pstCmd->stAns._stTApiKeyValue.GetValue("is_yellow_year_vip"));
                pstMsgTencentInfo->set_yellow_vip_level(pstCmd->stAns._stTApiKeyValue.GetValue("yellow_vip_level"));
                pstMsgTencentInfo->set_is_yellow_high_vip(pstCmd->stAns._stTApiKeyValue.GetValue("is_yellow_high_vip"));

                if (pstMsgTencentInfo->is_yellow_vip() != "0")
                {
                    bIsYellow = true;
                }
                else
                {
                    bIsYellow = false;
                }
            }
        }
    }

    //获取平台信息
    if (stPlayerOnlineData._bIsTencentLogin)
    {
        if (!bHasGetTencentUserInfo)
        {
            bHasGetTencentUserInfo = true;

            //平台校验登录
            CCmdApi* pstCmd = (CCmdApi*)CT_CMDFACTORY->CreateCmd(ID_MAINAPI_TAPI);
            if (!pstCmd)
            {
                CT_WARNING(("create cmd error"));
                return AnsClients(RET_SYS_ERROR);
            }

            pstCmd->pstMainCtrl = CMainCtrl::m_pstMain;
            pstCmd->stReq._ucReqType = CReqApi::API_TENCENT;
            pstCmd->stReq._szTApiName.Set("/v3/user/get_info");
            pstCmd->stReq._stTApiKeyValue = stPlayerOnlineData._stTencentApiKeyValue;
            pstCmd->stReq._stTApiKeyValue.SetValue("flag", "2"); //pf=qqgame时，必须输入该参数

            RegisterChild(pstCmd, true);
            return pstCmd->Do(NULL);
        }
    }
    else
    {
#ifdef _DEBUG
        MsgTencentInfo* pstMsgTencentInfo = stAns.mutable_tencent_info();

        if (TENCENT_LOGIN_FROM_PENGYOU == stPlayerOnlineData._ucTencentLoginFrom
            || TENCENT_LOGIN_FROM_QZONE == stPlayerOnlineData._ucTencentLoginFrom)
        {
            pstMsgTencentInfo->set_is_yellow_vip("1");
            pstMsgTencentInfo->set_is_yellow_year_vip("1");
            pstMsgTencentInfo->set_yellow_vip_level("1");
            pstMsgTencentInfo->set_is_yellow_high_vip("1");
        }

        if (TENCENT_LOGIN_FROM_QQGAME == stPlayerOnlineData._ucTencentLoginFrom
            || TENCENT_LOGIN_FROM_3366 == stPlayerOnlineData._ucTencentLoginFrom)
        {
            pstMsgTencentInfo->set_is_blue_vip("1");
            pstMsgTencentInfo->set_is_blue_year_vip("1");
            pstMsgTencentInfo->set_blue_vip_level("1");
            pstMsgTencentInfo->set_is_super_blue_vip("1");
        }

        if (TENCENT_LOGIN_FROM_3366 == stPlayerOnlineData._ucTencentLoginFrom)
        {
            pstMsgTencentInfo->set_p3366_level("1");
            pstMsgTencentInfo->set_p3366_grow_level("1");
        }
#endif
    }

    //获取最新的黄钻信息
    if (stPlayerOnlineData._bIsTencentLogin && !bHasGetYellowInfo)
    {
        bHasGetYellowInfo = true;

        //平台校验登录
        CCmdApi* pstCmd = (CCmdApi*)CT_CMDFACTORY->CreateCmd(ID_MAINAPI_TAPI);
        if (!pstCmd)
        {
            CT_WARNING(("create cmd error"));
            return AnsClients(RET_SYS_ERROR);
        }

        pstCmd->pstMainCtrl = CMainCtrl::m_pstMain;
        pstCmd->stReq._ucReqType = CReqApi::API_TENCENT;
        pstCmd->stReq._szTApiName.Set("/v3/user/is_vip");
        pstCmd->stReq._stTApiKeyValue = stPlayerOnlineData._stTencentApiKeyValue;

        RegisterChild(pstCmd, true);
        return pstCmd->Do(NULL);
    }

    iIndex = pstMainCtrl->m_stPlayerBaseInfoHash.HashFind(uiGID);
    if (iIndex < 0)
    {
        return AnsClients(RET_NO_USER);
    }

    CPlayerBaseInfo& stPlayerBaseInfo = pstMainCtrl->m_stPlayerBaseInfoHash[iIndex];
    stAns.set_gid(uiGID);

    MsgUserPos* pstUserPos = stAns.mutable_pos();
    pstUserPos->set_map_id(stPlayerBaseInfo._uiMapID);
    pstUserPos->set_pos_x(stPlayerBaseInfo._usXPos == 0xFFFF ? -1 : stPlayerBaseInfo._usXPos);
    pstUserPos->set_pos_y(stPlayerBaseInfo._usYPos == 0xFFFF ? -1 : stPlayerBaseInfo._usYPos);

    stAns.set_is_inited(stPlayerBaseInfo._ucIsInited);

    if (stPlayerBaseInfo._ucIsInited != 1)
    {
        MsgRoleInfo* pstMsgRoleInfo = stAns.mutable_info();
        pstMsgRoleInfo->set_name(stPlayerBaseInfo._sRoleName());

        MsgObjBase* pstObjBase = pstMsgRoleInfo->mutable_base_info();
        pstObjBase->set_sex(stPlayerBaseInfo._ucIsMale);
        pstObjBase->set_career(stPlayerBaseInfo._ucCareer);
        pstObjBase->set_level(stPlayerBaseInfo._shLevel);

        return AnsClients(RET_OK);
    }

    iIndex = pstMainCtrl->m_stPlayerDetailInfoHash.HashFind(uiGID);
    if (iIndex < 0)
    {
        CT_ERROR(("not found user %u", uiGID));
        return AnsClients(RET_SYS_ERROR);
    }
    CPlayerDetailInfo& stPlayerDetailInfo = pstMainCtrl->m_stPlayerDetailInfoHash[iIndex];

    iIndex = pstMainCtrl->m_stPlayerSnsCommInfoHash.HashFind(uiGID);
    if (iIndex < 0)
    {
        CT_ERROR(("no user %u", uiGID));
        return AnsClients(RET_NO_USER);
    }
    CPlayerSnsCommInfo& stPlayerSnsCommInfo = pstMainCtrl->m_stPlayerSnsCommInfoHash[iIndex];
    
    pstUserPos->set_map_id(stPlayerOnlineData._uiNowMapID);

    if (bIsYellow || bIsBlue) //平台VIP用户缺省送VIP1级
    {
        pstMainCtrl->m_stVipMgr.SetYellowDefaultVip(stPlayerBaseInfo);
    }

    MsgUserGold* pstUserGold = stAns.mutable_gold();
    pstUserGold->set_vip_level(stPlayerBaseInfo._chVipLevel);
    pstUserGold->set_gold(stPlayerBaseInfo._iGold);
    pstUserGold->set_romany(stPlayerBaseInfo._iRomany);

    CTSizeString<50> szTemp;
    szTemp.Set("%lld", stPlayerBaseInfo._i64Silver);
    pstUserGold->set_silver(szTemp());

    pstMainCtrl->m_stRoleMgr.CopyRoleInfo(stPlayerBaseInfo, stPlayerDetailInfo,
        stPlayerOnlineData, stPlayerSnsCommInfo, *(stAns.mutable_info()));

    //副本信息
    unsigned short usInstanceID = 0;
    for (int i = CInstanceConfigData::INSTANCE_TYPE_MIN; i <= CInstanceConfigData::INSTANCE_TYPE_MAX; ++i)
    {
        MsgInstanceInfo* pstInstanceInfo = stAns.add_instances();
        pstInstanceInfo->set_type(i);

        iRet = pstMainCtrl->m_stInstanceMgr.GetOpenStat(stPlayerOnlineData._stUserInstance, stPlayerOnlineData._stUserTask, i, usInstanceID);
        pstInstanceInfo->set_open_to(usInstanceID);

        iRet = pstMainCtrl->m_stInstanceMgr.GetFinishedStat(stPlayerOnlineData._stUserInstance, i, usInstanceID);
        pstInstanceInfo->set_acc_to(usInstanceID);

        CInstanceDetailStatData stDetailStatData;
        pstMainCtrl->m_stInstanceMgr.GetInstanceDetailStat(stPlayerOnlineData._stUserInstance, i, stDetailStatData);
        pstInstanceInfo->set_enemy_to(stDetailStatData.ucNowAccomplishPos);
    }

    //卡片分数
    unsigned int uiCardPoint = 0;
    pstMainCtrl->m_stCardMgr.GetCardPoint(stPlayerOnlineData._stUserCard, stPlayerDetailInfo._stPlayerWareCard, uiCardPoint);
    stAns.set_card_point(uiCardPoint);

    return AnsClients(RET_OK);
}

int CCmdGetUserInfo::AnsClients(int iRet)
{
    if (iRet)
    {
        CT_ERROR(("get user info error gid = %u, ret = %d", uiGID, iRet));
    }
    
    pstMainCtrl->m_stEncodeBuf.Clear();

    stMsgHead.set_msgret(iRet);
    stMsgHead.set_msgtype(CSMsgDef::EMT_ANSWER);

    if (iRet != RET_OK)
    {
        pstMainCtrl->ReturnMsgHead(stMsgHead, stEnpHead);
        return Done(iRet);
    }

    pstMainCtrl->EncodePBMsg(stMsgHead, pstMainCtrl->m_stEncodeBuf);
    pstMainCtrl->EncodePBMsg(stAns, pstMainCtrl->m_stEncodeBuf);
    if (pstMainCtrl->AnswerToClient(stEnpHead, pstMainCtrl->m_stEncodeBuf, true))
    {
        CT_WARNING((""));
        return Done(RET_SYS_ERROR);
    }

    int iIndex = pstMainCtrl->m_stPlayerBaseInfoHash.HashFind(uiGID);
    if (iIndex < 0)
    {
        return Done(RET_NO_USER);
    }
    CPlayerBaseInfo& stPlayerBaseInfo = pstMainCtrl->m_stPlayerBaseInfoHash[iIndex];

    if (stPlayerBaseInfo._ucIsInited != 1)
    {
        return Done(RET_OK);
    }

    iIndex = pstMainCtrl->m_stPlayerDetailInfoHash.HashFind(uiGID);
    if (iIndex < 0)
    {
        return Done(RET_NO_USER);
    }
    CPlayerDetailInfo& stPlayerDetailInfo = pstMainCtrl->m_stPlayerDetailInfoHash[iIndex];

    
    iIndex = pstMainCtrl->m_stPlayerDetailEx1InfoHash.HashFind(uiGID);
    if (iIndex < 0)
    {
        CT_ERROR(("no user %u", uiGID));
        return Done(RET_NO_USER);
    }
    CPlayerDetailInfoEx1& stPlayerDetailEx1 = pstMainCtrl->m_stPlayerDetailEx1InfoHash[iIndex];
    
    iIndex = pstMainCtrl->m_stPlayerOnlineDataHash.HashFind(uiGID);
    if (iIndex < 0)
    {
        return Done(RET_NO_USER);
    }
    CPlayerOnlineData& stPlayerOnlineData = pstMainCtrl->m_stPlayerOnlineDataHash[iIndex];

    unsigned int uiNotifyType = NOTIFY_ZONE_INFO | NOTIFY_BAG_INFO | NOTIFY_WARE_INFO | NOTIFY_MUSE_INFO;

    //宠物信息 
    if (pstMainCtrl->m_stCommConfigLoader.IsOpen(SYS_OPEN_COND_ID_3, stPlayerBaseInfo, stPlayerOnlineData))
    {
        uiNotifyType |= NOTIFY_PET_INFO;
    }

    //大区信息
    pstMainCtrl->m_stNotifyMgr.Notify(uiGID, uiNotifyType);

    //装备信息
    pstMainCtrl->m_stEquipMgr.SendEquipInfoToFront(stPlayerDetailInfo, stPlayerOnlineData, 0, stMsgHead, stEnpHead);

    //卡片背包
    pstMainCtrl->m_stCardMgr.SendCardBagInfoToFront(stPlayerOnlineData._stUserCard, stMsgHead, stEnpHead);

    //主角身上的卡片
    pstMainCtrl->m_stCardMgr.SendCardOnRoleToFront(stPlayerOnlineData._stUserCard, stPlayerBaseInfo, stPlayerDetailInfo, stMsgHead, stEnpHead);

    //秘宝背包
    pstMainCtrl->m_stTreasureMgr.SendBriefTreasureToFront(stPlayerDetailInfo);

    //副本详细信息
    //副本评分信息
    pstMainCtrl->m_stInstanceMgr.SendInstanceGradeToFront(stPlayerOnlineData._stUserInstance, stPlayerOnlineData._stUserTask, stMsgHead, stEnpHead);

    //主动下发阵型
    if (pstMainCtrl->m_stCommConfigLoader.IsOpen(SYS_OPEN_COND_ID_1, stPlayerBaseInfo, stPlayerOnlineData))
    {
        pstMainCtrl->m_stMatrixMgr.NotifyMatrix(stPlayerBaseInfo, stPlayerDetailInfo, stPlayerOnlineData);
    }

    //下发时装
    pstMainCtrl->m_stFashionMgr.SendWingBagInfoToFront (stPlayerDetailEx1._stUserFasion, uiGID, stMsgHead, stEnpHead); 
    pstMainCtrl->m_stFashionMgr.SendDressBagInfoToFront (stPlayerDetailEx1._stUserFasion, uiGID, stMsgHead, stEnpHead); 

    pstMainCtrl->FlushSendCache();

    return Done(iRet);
}

//////////////////////////////////////////////////////////////////////////
CT_REGISTER_ASYNCCMD(ID_MAIN_LOGOUT , CCmdLogout);

int CCmdLogout::Do(void* pData)
{
    if (pstMainCtrl == NULL)
    {
        return Done(RET_SYSTEM_FAIL);
    }

    int iIndex = pstMainCtrl->m_stPlayerOnlineDataHash.HashFind(_uiGID);
    if (iIndex < 0)
    {
        CT_WARNING(("%u", _uiGID));
        return Done(RET_NO_USER);
    }

    CPlayerOnlineData& stPlayerOnlineData = pstMainCtrl->m_stPlayerOnlineDataHash[iIndex];
    _uiNowMapID = stPlayerOnlineData._uiNowMapID;

    LogicDo(RET_OK);
    return RET_OK;
}

int CCmdLogout::LogicDo(int iRet)
{
    if (iRet != 0)
    {
        return Done(iRet);
    }

    PREPARE_PLAYER_BASE_INFO(this, _uiGID);
    ASSERT_PLAYER_PREPARED(_uiGID);

    PREPARE_PLAYER_DETAIL_INFO(this, _uiGID);
    ASSERT_PLAYER_DETAIL_PREPARED(_uiGID);

    PREPARE_PLAYER_SNS_DETAIL_INFO(this, _uiGID);
    ASSERT_PLAYER_SNS_DETAIL_PREPARED(_uiGID) ;

    int iIndex = pstMainCtrl->m_stPlayerBaseInfoHash.HashFind(_uiGID);
    if (iIndex < 0)
    {
        return Done(RET_NO_USER);
    }
    CPlayerBaseInfo& stPlayerBaseInfo = pstMainCtrl->m_stPlayerBaseInfoHash[iIndex];

    iIndex = pstMainCtrl->m_stPlayerDetailInfoHash.HashFind(_uiGID);
    if (iIndex < 0)
    {
        CT_ERROR(("not found user %u", _uiGID));
        return Done(RET_NO_USER);
    }
    CPlayerDetailInfo& stPlayerDetailInfo = pstMainCtrl->m_stPlayerDetailInfoHash[iIndex];

    iIndex = pstMainCtrl->m_stPlayerOnlineDataHash.HashFind(_uiGID);
    if (iIndex < 0)
    {
        CT_WARNING(("%u", _uiGID));
        return Done(RET_NO_USER);
    }
    CPlayerOnlineData& stPlayerOnlineData = pstMainCtrl->m_stPlayerOnlineDataHash[iIndex];

    //移出地图
    CSingleMapView::MAP_VIEW_NOTIFY_USERS_ARRAY astNotifyUsers;
    iRet = pstMainCtrl->m_stMapViews.LeaveMap(_uiNowMapID, stPlayerBaseInfo._uiGID, astNotifyUsers);
    if (iRet != 0)
    {
        CT_ERROR(("leave map error , %d", iRet));
        return Done(iRet);
    }

    PBMsgHead  stMsgHead;
    stMsgHead.set_msgid(ID_MAIN_MAP_MOVE);
    stMsgHead.set_msgtype(CSMsgDef::EMT_ANSWER);

    MsgAnsMoveTo stAns;
    stAns.set_gid(_uiGID);
    stAns.set_map_id(-1);

    pstMainCtrl->m_stEncodeBuf.Clear();
    pstMainCtrl->EncodePBMsg(stMsgHead, pstMainCtrl->m_stEncodeBuf);
    pstMainCtrl->EncodePBMsg(stAns, pstMainCtrl->m_stEncodeBuf);

    for (int i = 0; i < astNotifyUsers.Size(); ++i)
    {
        pstMainCtrl->NotifyOnlineUser(astNotifyUsers[i], pstMainCtrl->m_stEncodeBuf);
    }

    iIndex = pstMainCtrl->m_stPlayerSnsDetailInfoHash.HashFind(_uiGID);
    if (iIndex < 0)
    {
        CT_WARNING(("SetOffline, m_stPlayerSnsDetailInfoHash %u not find", _uiGID));
    }
    else
    {
        CPlayerSnsDetailInfo& stPlayerSnsDetailInfo = pstMainCtrl->m_stPlayerSnsDetailInfoHash[iIndex];

        //设置离线时间
        stPlayerSnsDetailInfo._stCommInfo._iLastLogOutTime = pstMainCtrl->m_iNow;

        //检查冥想系统是否开启
        if (pstMainCtrl->m_stCommConfigLoader.IsOpen(SYS_OPEN_COND_ID_12, stPlayerBaseInfo, stPlayerOnlineData))
        {
            //离线后自动进入冥想状态
            MsgMuseInfo stMuseInfo;
            pstMainCtrl->m_stMuseMgr.StartMuse(stPlayerBaseInfo, stPlayerDetailInfo._stMuseData, stMuseInfo);
        }

        CVarObjectKey stKey;
        stKey.m_chDataType = DT_PLAYER_DETAIL_INFO;
        stKey.m_u64ID = _uiGID;
        pstMainCtrl->UpdateData(stKey, stPlayerDetailInfo, VOP_UPDATE);

        //Defend:record user total online time
        //设置累计在线时间
        int iThisOnlineTime = pstMainCtrl->m_iNow - stPlayerSnsDetailInfo._stCommInfo._iLastLogInTime;
        if( stPlayerBaseInfo._iDefendValidInfo!=1 )
        {
            if (iThisOnlineTime < 0)
            {
                CT_WARNING(("this online time is %d, %u", iThisOnlineTime, _uiGID));
            }
            else
            {
                stPlayerBaseInfo._iDefTotalOnlineTime += iThisOnlineTime;
            }
        }

        stPlayerBaseInfo._iOnlineTimeSinceReg += iThisOnlineTime;

        //保存数据
        stKey.m_chDataType = DT_PLAYER_BASE_INFO;
        stKey.m_u64ID = stPlayerBaseInfo._uiGID;
        pstMainCtrl->UpdateData(stKey, stPlayerBaseInfo, VOP_UPDATE);

        stKey.m_chDataType = DT_PLAYER_SNS_DETAIL_INFO;
        stKey.m_u64ID = _uiGID;
        pstMainCtrl->UpdateData(stKey, stPlayerSnsDetailInfo, VOP_UPDATE);
    }

    //下线通知
    PBMsgHead stTipMsgHead = stMsgHead;
    stTipMsgHead.set_msgid(ID_MAIN_TIPS);
    stTipMsgHead.set_msgtype(CSMsgDef::EMT_ANSWER);
    stTipMsgHead.set_msgact(0);

    MsgTips stTips;
    stTips.set_type(6);
    stTips.set_dest_gid(_uiGID);

    pstMainCtrl->m_stEncodeBuf.Clear();
    pstMainCtrl->EncodePBMsg(stTipMsgHead, pstMainCtrl->m_stEncodeBuf);
    pstMainCtrl->EncodePBMsg(stTips, pstMainCtrl->m_stEncodeBuf);

    CTArray<unsigned int, MAX_PLAYER_ONLINE> astGIDArray;
    pstMainCtrl->m_stPlayerOnline.GetAllOnlineUser(astGIDArray);
    for (int i = 0; i < astGIDArray.Size(); ++i)
    {
        pstMainCtrl->NotifyOnlineUser(astGIDArray[i], pstMainCtrl->m_stEncodeBuf);
    }

    pstMainCtrl->FlushSendCache();

    return Done(RET_OK);
}

//////////////////////////////////////////////////////////////////////////
CT_REGISTER_ASYNCCMD(ID_MAIN_INIT_USER_INFO , CCmdInitUserInfo);

int CCmdInitUserInfo::Do(void* pData)
{
    CT_ASSERT(pData);

    //解析消息
    CCmdPBDoParam* pstParam = (CCmdPBDoParam*) pData;
    pstMainCtrl = (CMainCtrl*) pstParam->m_pMain;

    if (pstParam->m_pstMsgHead->msgid() != ID_MAIN_INIT_USER_INFO ||
        pstParam->m_pstMsgHead->msgtype() != CSMsgDef::EMT_REQUEST)
    {
        CT_ERROR(("Cmd Stat Err Cmd=%d CmdID=%d Tpye=%d",
            ID_MAIN_INIT_USER_INFO,
            pstParam->m_pstMsgHead->msgid(),
            pstParam->m_pstMsgHead->msgtype()));
        return Done(RET_SYS_ERROR);
    }

    stMsgHead = *(pstParam->m_pstMsgHead);
    stEnpHead = *(pstParam->m_pstEnpHead);
    int iRet = pstMainCtrl->DecodePBMsg(stReq, pstParam);
    if (iRet)
    {
        return AnsClients(iRet);
    }
    //消息解析结束

    //检查登录
    _uiGID = stReq.gid();

    if (!_bIsHttpInit)
    {
        iRet = pstMainCtrl->CheckLogin(_uiGID, stEnpHead);
        if (iRet != RET_OK)
        {
            return AnsClients(iRet);
        }
    }

    LogicDo(RET_OK);
    return RET_OK;
}

int CCmdInitUserInfo::LogicDo(int iRet)
{
    if (iRet != 0)
    {
        return AnsClients(iRet);
    }

    PREPARE_PLAYER_BASE_INFO(this, _uiGID);
    ASSERT_PLAYER_PREPARED(_uiGID);

    PREPARE_PLAYER_DETAIL_INFO(this, _uiGID);
    ASSERT_PLAYER_DETAIL_PREPARED(_uiGID);

    PREPARE_PLAYER_DETAIL_EX1_INFO(this, _uiGID);
    ASSERT_PLAYER_DETAIL_EX1_INFO(_uiGID);

    PREPARE_UNACT_PARTNER_INFO(this, _uiGID);
    ASSERT_UNACT_PARTNER_PREPARED(_uiGID);

    PREPARE_PLAYER_SNS_DETAIL_INFO(this, _uiGID);
    PREPARE_PLAYER_ONLINE_DATA(this, _uiGID);

    int iIndex = pstMainCtrl->m_stPlayerBaseInfoHash.HashFind(_uiGID);
    if (iIndex < 0)
    {
        return AnsClients(RET_NO_USER);
    }
    CPlayerBaseInfo& stPlayerBaseInfo = pstMainCtrl->m_stPlayerBaseInfoHash[iIndex];

    iIndex = pstMainCtrl->m_stPlayerDetailInfoHash.HashFind(_uiGID);
    if (iIndex < 0)
    {
        return AnsClients(RET_NO_USER);
    }
    CPlayerDetailInfo& stPlayerDetailInfo = pstMainCtrl->m_stPlayerDetailInfoHash[iIndex];

    iIndex = pstMainCtrl->m_stPlayerDetailEx1InfoHash.HashFind(_uiGID);
    if (iIndex < 0)
    {
        return AnsClients(RET_NO_USER);
    }
    CPlayerDetailInfoEx1& stPlayerDetailEx1Info = pstMainCtrl->m_stPlayerDetailEx1InfoHash[iIndex];

    if (stPlayerBaseInfo._ucIsInited != 0)
    {
        return AnsClients(ERROR_USER_INFO_HAS_INITED);
    }

    iIndex = pstMainCtrl->m_stPlayerOnlineDataHash.HashFind(_uiGID);
    if (iIndex < 0)
    {
        CT_ERROR(("user %u not in m_stPlayerOnlineDataHash", _uiGID));
        pstMainCtrl->SetOffline(_uiGID, stEnpHead);
        return AnsClients(RET_NO_USER);
    }
    CPlayerOnlineData& stPlayerOnlineData = pstMainCtrl->m_stPlayerOnlineDataHash[iIndex];

    iIndex = pstMainCtrl->m_stPlayerSnsDetailInfoHash.HashFind(_uiGID);
    if (iIndex < 0)
    {
        return AnsClients(RET_NO_USER);
    }
    CPlayerSnsDetailInfo& stPlayerSnsDetailInfo = pstMainCtrl->m_stPlayerSnsDetailInfoHash[iIndex];

    iIndex = pstMainCtrl->m_stUnactPartnerInfoHash.HashFind(_uiGID);
    if (iIndex < 0)
	{
        CT_ERROR(("no unact partner data user(%u)", _uiGID));
        return AnsClients(RET_NO_USER);
	}
	CUnactPartnerInfo& stUnactPartnerInfo = pstMainCtrl->m_stUnactPartnerInfoHash[iIndex];

    /************************************************************************/
    /*                        基础信息初始化                            */
    /************************************************************************/

    //创建角色时需要初始化的调用全部放在这里

    //选择性别和职业
    if (stReq.career() != 0 && stPlayerBaseInfo._ucCareer == 0)
    {        
        stPlayerBaseInfo._ucIsMale = (stReq.is_male() == 1 ? 1 : 0);
        stPlayerSnsDetailInfo._stCommInfo._ucIsMale = stPlayerBaseInfo._ucIsMale;

        stPlayerBaseInfo._ucCareer = (unsigned char)stReq.career() & 0x7F;
        if (stPlayerBaseInfo._ucCareer < CAREER_BEGIN || stPlayerBaseInfo._ucCareer > CAREER_END)
        {
            return AnsClients(ERROR_WRONG_CAREER);
        }
        stPlayerSnsDetailInfo._stCommInfo._ucCareer = stPlayerBaseInfo._ucCareer;

        pstMainCtrl->m_stTaskMgr.TriggerDoSomeOpt(stPlayerOnlineData._stUserTask, TASK_OPT_ID_100, 1);
        stPlayerOnlineData._stUserTask.GetData(stPlayerBaseInfo._stUserTaskData);
    }
    
    //输入昵称
    if (stReq.role_name().size() != 0 && stPlayerBaseInfo._sRoleName.GetDataLen() == 0)
    {
        CTSizeString<ROLENAME_LEN> szRoleName;
        szRoleName.Set("%s", stReq.role_name().c_str());

        if (!_bHasCheckSenWord)
        {
            _bHasCheckSenWord = true;

            iRet = CheckNewRoleName(szRoleName);
            if (iRet != RET_OK)
            {
                return AnsClients(iRet);
            }

            //在平台检查
            if (!_bIsHttpInit && stPlayerOnlineData._bIsTencentLogin)
            {
                CCmdApi* pstCmd = (CCmdApi*)CT_CMDFACTORY->CreateCmd(ID_MAINAPI_TAPI);
                if (!pstCmd)
                {
                    CT_WARNING(("create cmd error"));
                    return AnsClients(RET_SYS_ERROR);
                }

                pstCmd->pstMainCtrl = pstMainCtrl;
                pstCmd->stReq._ucReqType = CReqApi::API_TENCENT;
                pstCmd->stReq._szTApiName.Set("/v3/csec/word_filter");
                pstCmd->stReq._stTApiKeyValue = stPlayerOnlineData._stTencentApiKeyValue;
                pstCmd->stReq._stTApiKeyValue.SetValue("content", szRoleName());

                uint64 u64MsgID = CT_UINT64_MAKE(_uiGID, pstMainCtrl->m_iNow);
                pstCmd->stReq._stTApiKeyValue.SetValue("msgid", CTStringUtils::Uint64ToString(u64MsgID, 16));

                RegisterChild(pstCmd, true);
                return pstCmd->Do(NULL);
            } 
        }
        else
        {
            if (m_pstChild && ID_MAINAPI_TAPI == m_pstChild->GetCmdID())
            {
                CCmdApi* pstCmd = (CCmdApi*)m_pstChild;
                if (pstCmd->stReq._szTApiName == "/v3/csec/word_filter")
                {
                    if (atoi(pstCmd->stAns._stTApiKeyValue.GetValue("is_dirty")) != 0)
                    {
                        return AnsClients(ERROR_HAS_SEN_WORD);
                    }
                }
            }
        }

        stPlayerBaseInfo._sRoleName.Set("%s@%d", szRoleName(), CONF->ZoneID);

        //放入role name全局hash
        CRolenameKey stRolenameKey;
        stRolenameKey.Init(stPlayerBaseInfo._sRoleName);
        iIndex = pstMainCtrl->m_stRolenameHash.HashAlloc(stRolenameKey);
        if (iIndex < 0)
        {
            CT_ERROR(("add to role name hash error, ret %d", iIndex));
            return AnsClients(RET_SYS_ERROR);
        }
        pstMainCtrl->m_stRolenameHash[iIndex] = _uiGID;

        pstMainCtrl->m_stTaskMgr.TriggerDoSomeOpt(stPlayerOnlineData._stUserTask, TASK_OPT_ID_102, 1);
        stPlayerOnlineData._stUserTask.GetData(stPlayerBaseInfo._stUserTaskData);
    }

    if (stPlayerBaseInfo._ucCareer != 0 && stPlayerBaseInfo._sRoleName.GetDataLen() != 0)       //完成初始化的条件
    {
        stPlayerBaseInfo._shLevel = 1;

        stPlayerOnlineData._bIsInitFinish = false;

        /*
        //激活第一个任务
        CTaskIDData stFirstTaskID;
        stFirstTaskID._uiBranchID = 0;
        stFirstTaskID._uiTaskID = TASK_FIRST_TASK_ID;
        stPlayerBaseInfo._stUserTaskData._astOpenTaskIDs.AddOneItem(stFirstTaskID);

        //接第一个任务
        CTaskID stFirstAccTask;
        stFirstAccTask._uiBranchID = 0;
        stFirstAccTask._uiTaskID = TASK_FIRST_TASK_ID;
        pstMainCtrl->m_stTaskMgr.AcceptTask(stFirstAccTask, stPlayerOnlineData._stUserTask);
        stPlayerOnlineData._stUserTask.GetData(stPlayerBaseInfo._stUserTaskData);
        */

        stPlayerBaseInfo._ucIsInited = 1;
        stPlayerSnsDetailInfo._stCommInfo._sRoleName = stPlayerBaseInfo._sRoleName;
        stPlayerSnsDetailInfo._stCommInfo._ucIsInited = 1;

        //用户首次登陆的注册,需要放在 CPlayerSnsDetailInfo 结构初始化之后调用
        pstMainCtrl->m_stOssMgr.TriggerRegister(stPlayerBaseInfo._uiGID);
        pstMainCtrl->m_stCompassMgr.Register(stPlayerBaseInfo._uiGID);

        //自动招募第一个伙伴莫甘娜
        MsgAnsPartner stMsgPartnerAns;
    	iRet = pstMainCtrl->m_stPartnerMgr.PartnerJoin(INIT_PARTNER_ID_BORTH,
            CPartnerMgr::PARTNER_JOIN_TYPE_SYSTEM, stPlayerBaseInfo,
            stPlayerDetailInfo, stUnactPartnerInfo, stPlayerOnlineData,
            stPlayerDetailEx1Info, stMsgPartnerAns);
        if (iRet)
        {
            CT_ERROR(("join first partner error, ret %d", iRet));
        }

        //初始化角色第一个阵形
        iRet = pstMainCtrl->m_stMatrixMgr.InitMatrix(stPlayerBaseInfo,
            stPlayerDetailInfo);
        if (iRet)
        {
            CT_ERROR(("Init matrix error, ret %d", iRet));
        }

        //自动上阵第一个伙伴莫甘娜
        MsgReqMatrix stMsgMatrixReq;
        MsgAnsMatrix stMsgMatrixAns;

        stMsgMatrixReq.set_gid(stPlayerBaseInfo._uiGID);
        stMsgMatrixReq.set_sub_type(CMatrixMgr::CMD_MATRIX_SUB_ADD);
        stMsgMatrixReq.set_matrix_idx(0);
        MsgMatrixUnit* pstMatrixUnit = stMsgMatrixReq.add_unit_datas();
        if (pstMatrixUnit)
        {
            pstMatrixUnit->set_type(GAME_OBJ_TYPE_PARTNER);
            pstMatrixUnit->set_id(INIT_PARTNER_ID_BORTH);
            pstMatrixUnit->set_pos(CMatrixMgr::MATRIX_POS_NUMBER_A);
        }

        iRet = pstMainCtrl->m_stMatrixMgr.AddToMatrix(stPlayerBaseInfo,
            stPlayerDetailInfo, stPlayerOnlineData, stMsgMatrixReq,
            stMsgMatrixAns);
        if (iRet)
        {
            CT_ERROR(("add first partner to matrix error, ret %d", iRet));
        }

        //精力
        stPlayerBaseInfo._stUserEnergy._shEnergy = MAX_ENERGY_GROW_COUNT;

        //初始化神秘商店
        iRet = pstMainCtrl->m_stShopMgr.InitMysticalShop(stPlayerBaseInfo._uiGID, stPlayerOnlineData._stUserShop,
            pstMainCtrl->m_iNow, stPlayerDetailInfo._stShopData);
        if (iRet)
        {
            CT_ERROR(("Init mystical shop error, ret %d", iRet));
        }

        //初始化用户的每日任务
        iRet = pstMainCtrl->m_stDailyTaskMgr.InitForNewUser(stPlayerBaseInfo._stUserDailyTaskData);
        if (iRet != 0)
        {
            CT_WARNING(("init dailytask user data error, ret %d", iRet));
        }

        //初始化新手目标
        pstMainCtrl->m_stNewbieTaskMgr.InitTask(stPlayerDetailEx1Info._stNewbieTaskUserData, _uiGID, pstMainCtrl->m_iNow);

        //初始化背包和仓库
        stPlayerDetailInfo._stUserStorage._shMaxBagGridCount = SYS_DEFAULT_GRID_NUM_BAG;
        stPlayerDetailInfo._stUserStorage._shMaxWareHouseGridCount = SYS_DEFAULT_GRID_NUM_WAREHOUSE;

        //初始化上课系统
        iRet = pstMainCtrl->m_stLessonMgr.NewUserInitData(stPlayerDetailInfo._stUserLessonData);
        if (iRet != 0)
        {
            CT_WARNING(("init lesson data error, ret %d", iRet));
        }

        //分配用户装备
        iRet = pstMainCtrl->m_stEquipMgr.AllocUserFirstEquip(stPlayerBaseInfo._ucCareer,
            stPlayerOnlineData._stUserEquip, stPlayerOnlineData._stUserStorage);
        if (iRet)
        {
            CT_ERROR(("alloc user first, ret %d", iRet));
        }

        pstMainCtrl->m_stEquipMgr.GetData(stPlayerOnlineData._stUserEquip, stPlayerDetailInfo._stUserEquip);
        pstMainCtrl->m_stStorageMgr.GetData(stPlayerOnlineData._stUserStorage, stPlayerDetailInfo._stUserStorage);

        //初始化花园，加块初始的土地
        CGardenLandData stLandData;
        stLandData._ucLandLevel = 1;
        stPlayerSnsDetailInfo._stMyInfo._stGardenData._astLand.AddOneItem(stLandData);

        iRet = stPlayerOnlineData.InitData(_uiGID, stPlayerBaseInfo, stPlayerDetailInfo, stPlayerDetailEx1Info, stPlayerSnsDetailInfo);
        if (RET_OK != iRet)
        {
            return AnsClients(iRet);
        }

        pstMainCtrl->FindPlayerCacheData(stPlayerBaseInfo._uiGID);

        //////////////////////////////////////////////////////////////////////////
        if (!_bIsHttpInit)
        {
            //进入场景
            iRet = pstMainCtrl->m_stMapViews.IntoMap(stPlayerOnlineData._uiNowMapID, stPlayerBaseInfo._uiGID, false);
            if (iRet != 0)
            {
                CT_WARNING(("into map error, ret %d", iRet));
            }
        }

        //登录账单
        pstMainCtrl->m_stOssMgr.TriggerCreate(stPlayerBaseInfo);
#if 0
        if (stPlayerOnlineData._bIsTencentLogin)
        {
            CCmdApi* pstCmd = (CCmdApi*)CT_CMDFACTORY->CreateCmd(ID_MAINAPI_TAPI);
            if (pstCmd)
            {
                pstCmd->pstMainCtrl = CMainCtrl::m_pstMain;
                pstCmd->stReq._ucReqType = CReqApi::API_TENCENT;
                pstCmd->stReq._szTApiName.Set("/v3/t/add_t");
                pstCmd->stReq._stTApiKeyValue = stPlayerOnlineData._stTencentApiKeyValue;
                pstCmd->stReq._stTApiKeyValue.SetValue("content", "我发现了一个好游戏，史上首款哈利波特魔法学院题材，创新的直线布阵战斗方式，百轮怪物攻城气势宏大，60秒快速体验惊心动魄，一起来玩吧！http://rc.qzone.qq.com/100711417");
                pstCmd->stReq._stTApiKeyValue.SetValue("clientip", CTStringUtils::UintToString(stEnpHead.uiRemoteIP));

                uint64 u64MsgID = CT_UINT64_MAKE(_uiGID, pstMainCtrl->m_iNow);
                pstCmd->stReq._stTApiKeyValue.SetValue("msgid", CTStringUtils::Uint64ToString(u64MsgID, 16));

                pstCmd->Do(NULL);
            }

        }   
#endif
    }

    //保存数据
    CVarObjectKey stKey;
    stKey.m_chDataType = DT_PLAYER_BASE_INFO;
    stKey.m_u64ID = stPlayerBaseInfo._uiGID;
    pstMainCtrl->UpdateData(stKey, stPlayerBaseInfo, VOP_UPDATE);

    stKey.m_chDataType = DT_PLAYER_DETAIL_INFO;
    stKey.m_u64ID = stPlayerDetailInfo._uiGID;
    pstMainCtrl->UpdateData(stKey, stPlayerDetailInfo, VOP_UPDATE);

    stKey.m_chDataType = DT_PLAYER_SNS_DETAIL_INFO;
    stKey.m_u64ID = stPlayerSnsDetailInfo._uiGID;
    pstMainCtrl->UpdateData(stKey, stPlayerSnsDetailInfo, VOP_UPDATE);

    return AnsClients(RET_OK);
}

int CCmdInitUserInfo::AnsClients(int iRet)
{
    if (!_bIsHttpInit)
    {
        stMsgHead.set_msgret(iRet);
        stMsgHead.set_msgtype(CSMsgDef::EMT_ANSWER);
        pstMainCtrl->ReturnMsgHead(stMsgHead, stEnpHead);
    }

    _iRet = iRet;

    return Done(iRet);
}

int CCmdInitUserInfo::CheckNewRoleName(CTSizeString<ROLENAME_LEN>& szRoleName)
{
    int iRet = 0;
    CMainCtrl* pstMainCtrl = CMainCtrl::m_pstMain;

    //检查字符集编码方式
    const char * sNowCharSet = pstMainCtrl->m_stCharSetConvertMgr.GetCharset(szRoleName(), szRoleName.GetDataLen(), iRet);
    if (sNowCharSet == NULL || iRet != 0)
    {
        CT_WARNING(("ret = %d, char set %s", iRet, (sNowCharSet == NULL ? "NULL" : sNowCharSet)));
        return ERROR_WRONG_NAME_CHAR_SET;
    }

    if (strncmp("UTF-8", sNowCharSet, sizeof("UTF-8")) != 0
        && strlen(sNowCharSet) != 0)
    {
        CT_WARNING(("char set %s, name = %s", (sNowCharSet == NULL ? "NULL" : sNowCharSet), szRoleName()));
        return ERROR_WRONG_NAME_CHAR_SET;
    }

    //检查长度
    int iNameLen = CTStringUtils::GetUtf8StrLen(szRoleName());
    if (iNameLen < MIN_ROLENAME_LEN || iNameLen > MAX_ROLENAME_LEN)
    {
        return ERROR_WRONG_NAME;
    }

    //检查单字节屏蔽字
    for (int i = 0; i < szRoleName.GetDataLen(); ++i)
    {
        unsigned char ucChar = szRoleName()[i];
        if (ucChar < 128)
        {
            if ((ucChar >= '0' && ucChar <= '9')
                || (ucChar >= 'a' && ucChar <= 'z')
                || (ucChar >= 'A' && ucChar <= 'Z'))
            {
                continue;
            }
            else
            {
                return ERROR_HAS_SEN_WORD;
            }
        }
    }
    
    /*
    //检查敏感字
    iRet = pstMainCtrl->m_stSenWordMgr.queryNickName( szRoleName() );
    if (iRet > 0)
    {
        CT_TRACE(("role name = %s, ret %d, sen word %s", szRoleName(), iRet, iRet==2?"special char":"sensitive word"));
        return ERROR_HAS_SEN_WORD;
    }
    */
    /*char * sSenWord = NULL;
    iRet = pstMainCtrl->m_stSenWordMgr.querySenWord(szRoleName(), &sSenWord);
    if (iRet == 0 && sSenWord != NULL)
    {
        CT_TRACE(("role name = %s, ret %d, sen word %s", szRoleName(), iRet, sSenWord));
        return ERROR_HAS_SEN_WORD;
    }*/

    //检查重复
    T_SAME_ROLE_NAME_INDEXS aiIndexs;
    pstMainCtrl->m_stRolenameHash.HashFind(szRoleName, aiIndexs);
    if (aiIndexs.Size() > 0)
    {
        return ERROR_ROLE_NAME_EXIST;
    }

    return 0;
}

//////////////////////////////////////////////////////////////////////////

CT_REGISTER_ASYNCCMD(ID_MAIN_CHECK_ROLENAME , CCmdCheckRolename);

int CCmdCheckRolename::Do(void* pData)
{
    CT_ASSERT(pData);

    //解析消息
    CCmdPBDoParam* pstParam = (CCmdPBDoParam*) pData;
    pstMainCtrl = (CMainCtrl*) pstParam->m_pMain;

    if (pstParam->m_pstMsgHead->msgid() != ID_MAIN_CHECK_ROLENAME ||
        pstParam->m_pstMsgHead->msgtype() != CSMsgDef::EMT_REQUEST)
    {
        CT_ERROR(("Cmd Stat Err Cmd=%d CmdID=%d Tpye=%d",
            ID_MAIN_CHECK_ROLENAME,
            pstParam->m_pstMsgHead->msgid(),
            pstParam->m_pstMsgHead->msgtype()));
        return Done(RET_SYS_ERROR);
    }

    stMsgHead = *(pstParam->m_pstMsgHead);
    stEnpHead = *(pstParam->m_pstEnpHead);
    int iRet = pstMainCtrl->DecodePBMsg(stReq, pstParam);
    if (iRet)
    {
        return AnsClients(iRet);
    }
    //消息解析结束

    //检查登录
    uiGID = stReq.gid();
    iRet = pstMainCtrl->CheckLogin(uiGID, stEnpHead);
    if (iRet != RET_OK)
    {
        return AnsClients(iRet);
    }

    CTSizeString<ROLENAME_LEN> szRolename;
    szRolename.Set("%s", stReq.name().c_str());

    stAns.set_result(CCmdInitUserInfo::CheckNewRoleName(szRolename));

    return AnsClients(RET_OK);
}

int CCmdCheckRolename::AnsClients(int iRet)
{
    stMsgHead.set_msgret(iRet);
    stMsgHead.set_msgtype(CSMsgDef::EMT_ANSWER);

    if (iRet != RET_OK)
    {
        pstMainCtrl->ReturnMsgHead(stMsgHead, stEnpHead);
        return Done(iRet);
    }

    pstMainCtrl->m_stEncodeBuf.Clear();
    pstMainCtrl->EncodePBMsg(stMsgHead, pstMainCtrl->m_stEncodeBuf);
    pstMainCtrl->EncodePBMsg(stAns, pstMainCtrl->m_stEncodeBuf);
    if (pstMainCtrl->AnswerToClient(stEnpHead, pstMainCtrl->m_stEncodeBuf, true))
    {
        CT_WARNING((""));
        return Done(RET_SYS_ERROR);
    }

    return Done(iRet);
}

//////////////////////////////////////////////////////////////////////////

CT_REGISTER_ASYNCCMD(ID_MAIN_USER_GUIDE , CCmdUserGuideInfo);

int CCmdUserGuideInfo::Do(void* pData)
{
    CT_ASSERT(pData);

    //解析消息
    CCmdPBDoParam* pstParam = (CCmdPBDoParam*) pData;
    pstMainCtrl = (CMainCtrl*) pstParam->m_pMain;

    if (pstParam->m_pstMsgHead->msgid() != ID_MAIN_USER_GUIDE ||
        pstParam->m_pstMsgHead->msgtype() != CSMsgDef::EMT_REQUEST)
    {
        CT_ERROR(("Cmd Stat Err Cmd=%d CmdID=%d Tpye=%d",
            ID_MAIN_USER_GUIDE,
            pstParam->m_pstMsgHead->msgid(),
            pstParam->m_pstMsgHead->msgtype()));
        return Done(RET_SYS_ERROR);
    }

    stMsgHead = *(pstParam->m_pstMsgHead);
    stEnpHead = *(pstParam->m_pstEnpHead);
    int iRet = pstMainCtrl->DecodePBMsg(stReq, pstParam);
    if (iRet)
    {
        return AnsClients(iRet);
    }
    //消息解析结束

    //检查登录
    uiGID = stReq.gid();
    iRet = pstMainCtrl->CheckLogin(uiGID, stEnpHead);
    if (iRet != RET_OK)
    {
        return AnsClients(iRet);
    }

    return LogicDo(RET_OK);
}

int CCmdUserGuideInfo::LogicDo(int iRet)
{
    if (iRet)
    {
        return AnsClients(iRet);
    }

    PREPARE_PLAYER_SNS_DETAIL_INFO(this, uiGID);

    int iIndex = pstMainCtrl->m_stPlayerSnsDetailInfoHash.HashFind(uiGID);
    if (iIndex < 0)
    {
        return AnsClients(RET_SYS_ERROR);
    }
    CPlayerSnsDetailInfo& stPlayerSnsDetailInfo = pstMainCtrl->m_stPlayerSnsDetailInfoHash[iIndex];
    CUserGuideData& stUserGuideData = stPlayerSnsDetailInfo._stMyInfo._stUserGuideData;

    stAns.set_opt(stReq.opt());
    switch (stReq.opt())
    {
    case 1: // 存
        {
            stUserGuideData._szInfo.Set("%s", stReq.data().c_str());

            CVarObjectKey stKey;

            stKey.m_chDataType = DT_PLAYER_SNS_DETAIL_INFO;
            stKey.m_u64ID = stPlayerSnsDetailInfo._uiGID;
            pstMainCtrl->UpdateData(stKey, stPlayerSnsDetailInfo, VOP_UPDATE);
        }
        break;
    case 2: //取
        {
            stAns.set_data(stUserGuideData._szInfo());
        }
        break;
    default:
        return AnsClients(RET_SYS_ERROR);
    }
    
    return AnsClients(iRet);
}

int CCmdUserGuideInfo::AnsClients(int iRet)
{
    stMsgHead.set_msgret(iRet);
    stMsgHead.set_msgtype(CSMsgDef::EMT_ANSWER);

    if (iRet != RET_OK)
    {
        pstMainCtrl->ReturnMsgHead(stMsgHead, stEnpHead);
        return Done(iRet);
    }

    pstMainCtrl->m_stEncodeBuf.Clear();
    pstMainCtrl->EncodePBMsg(stMsgHead, pstMainCtrl->m_stEncodeBuf);
    pstMainCtrl->EncodePBMsg(stAns, pstMainCtrl->m_stEncodeBuf);
    if (pstMainCtrl->AnswerToClient(stEnpHead, pstMainCtrl->m_stEncodeBuf, true))
    {
        CT_WARNING((""));
        return Done(RET_SYS_ERROR);
    }

    return Done(iRet);
}

//////////////////////////////////////////////////////////////////////////

CT_REGISTER_ASYNCCMD(ID_MAIN_GET_MULTI_TENCENT_INFO , CCmdGetMultiTencentInfo);

int CCmdGetMultiTencentInfo::Do(void* pData)
{
    CT_ASSERT(pData);

    //解析消息
    CCmdPBDoParam* pstParam = (CCmdPBDoParam*) pData;
    pstMainCtrl = (CMainCtrl*) pstParam->m_pMain;

    if (pstParam->m_pstMsgHead->msgid() != ID_MAIN_GET_MULTI_TENCENT_INFO ||
        pstParam->m_pstMsgHead->msgtype() != CSMsgDef::EMT_REQUEST)
    {
        CT_ERROR(("Cmd Stat Err Cmd=%d CmdID=%d Tpye=%d",
            ID_MAIN_GET_MULTI_TENCENT_INFO,
            pstParam->m_pstMsgHead->msgid(),
            pstParam->m_pstMsgHead->msgtype()));
        return Done(RET_SYS_ERROR);
    }

    stMsgHead = *(pstParam->m_pstMsgHead);
    stEnpHead = *(pstParam->m_pstEnpHead);
    int iRet = pstMainCtrl->DecodePBMsg(stReq, pstParam);
    if (iRet)
    {
        return AnsClients(iRet);
    }
    //消息解析结束

    //检查登录
    uiGID = stReq.gid();
    iRet = pstMainCtrl->CheckLogin(uiGID, stEnpHead);
    if (iRet != RET_OK)
    {
        return AnsClients(iRet);
    }

    bHasSendMsg = false;

    return LogicDo(RET_OK);
}

int CCmdGetMultiTencentInfo::LogicDo(int iRet)
{
    if (iRet)
    {
        return AnsClients(iRet);
    }

    PREPARE_PLAYER_ONLINE_DATA(this, stReq.gid());

    int iIndex = pstMainCtrl->m_stPlayerOnlineDataHash.HashFind(uiGID);
    if (iIndex < 0)
    {
        CT_ERROR(("%u", uiGID));
        return AnsClients(RET_SYS_ERROR);
    }
    CPlayerOnlineData& stPlayerOnlineData = pstMainCtrl->m_stPlayerOnlineDataHash[iIndex];

    if (!stPlayerOnlineData._bIsTencentLogin)
    {
        return AnsClients(RET_OK);
    }

    if (stReq.dest_gid_size() > 100)
    {
        CT_ERROR(("%d", stReq.dest_gid_size()));
        return AnsClients(RET_OK);
    }

    CTSizeString<40960> szTmp;
    if (!bHasSendMsg)
    {
        bHasSendMsg = true;

        //平台校验登录
        CCmdApi* pstCmd = (CCmdApi*)CT_CMDFACTORY->CreateCmd(ID_MAINAPI_TAPI);
        if (!pstCmd)
        {
            CT_WARNING(("create cmd error"));
            return AnsClients(RET_SYS_ERROR);
        }

        pstCmd->pstMainCtrl = CMainCtrl::m_pstMain;
        pstCmd->stReq._ucReqType = CReqApi::API_TENCENT;
        pstCmd->stReq._szTApiName.Set("/v3/user/get_multi_info");

        CTLib::CTKeyValue& stApiKeyValue = pstCmd->stReq._stTApiKeyValue;
        stApiKeyValue =  stPlayerOnlineData._stTencentApiKeyValue;
        
        //拼装请求
        for (int i = 0; i < stReq.dest_gid_size(); ++i)
        {
            unsigned int uiDestGID = stReq.dest_gid(i);

            int iIndex = pstMainCtrl->m_stPlayerSnsCommInfoHash.HashFind(uiDestGID);
            if (iIndex < 0)
            {
                CT_WARNING(("%u", uiDestGID));
                continue;
            }
            CPlayerSnsCommInfo& stPlayerSnsCommInfo = pstMainCtrl->m_stPlayerSnsCommInfoHash[iIndex];

            szTmp.Cat("%s_", stPlayerSnsCommInfo._sUserToken());

            CUserTokenAndGID stUserTokenAndGID;
            stUserTokenAndGID.szUserToken = stPlayerSnsCommInfo._sUserToken;
            stUserTokenAndGID.uiGID = uiDestGID;
            _astUserTokenAndGID.AddOneItem(stUserTokenAndGID);
        }
        
        if (szTmp.GetDataLen() > 0)
        {
            szTmp.SetDataLen(szTmp.GetDataLen() - 1); //去掉末尾的'_'
        }

        stApiKeyValue.SetValue("fopenids", szTmp());

        RegisterChild(pstCmd, true);
        return pstCmd->Do(NULL);
    }

    if (!m_pstChild || ID_MAINAPI_TAPI != m_pstChild->GetCmdID())
    {
        return AnsClients(RET_SYS_ERROR);
    }
    
    CCmdApi* pstCmd = (CCmdApi*)m_pstChild;
    CTLib::CTKeyValue& stApiKeyValue = pstCmd->stAns._stTApiKeyValue; 
    
    std::string s;
    const std::string sDel = "|";
    std::vector<std::string> vOpenID, vIsYellowVip, vIsYellowYearVip, vYellowVipLevel, vIsYellowHighVip;

    s = stApiKeyValue.GetValue("items_openid");
    CTStringUtils::Split(s, sDel, vOpenID);
    unsigned int uiCount = vOpenID.size();
    
    s = stApiKeyValue.GetValue("items_is_yellow_vip");
    CTStringUtils::Split(s, sDel, vIsYellowVip);
    if (vIsYellowVip.size() != uiCount)
    {
        CT_ERROR((""));
        return AnsClients(RET_SYS_ERROR);
    }

    s = stApiKeyValue.GetValue("items_is_yellow_year_vip");
    CTStringUtils::Split(s, sDel, vIsYellowYearVip);
    if (vIsYellowYearVip.size() != uiCount)
    {
        CT_ERROR((""));
        return AnsClients(RET_SYS_ERROR);
    }

    s = stApiKeyValue.GetValue("items_yellow_vip_level");
    CTStringUtils::Split(s, sDel, vYellowVipLevel);
    if (vYellowVipLevel.size() != uiCount)
    {
        CT_ERROR((""));
        return AnsClients(RET_SYS_ERROR);
    }

    s = stApiKeyValue.GetValue("items_is_yellow_high_vip");
    CTStringUtils::Split(s, sDel, vIsYellowHighVip);
    if (vIsYellowHighVip.size() != uiCount)
    {
        CT_ERROR((""));
        return AnsClients(RET_SYS_ERROR);
    }
    
    for (unsigned int i = 0; i < vOpenID.size(); ++i)
    {
        CTSizeString<USER_TOKEN_LEN> szUserToken;
        szUserToken.Set("%s", vOpenID[i].c_str());

        MsgTencentInfo* pstMsgTencentInfo = stAns.add_info();
        pstMsgTencentInfo->set_gid(GetGidByToken(szUserToken));
        pstMsgTencentInfo->set_is_yellow_vip(vIsYellowVip[i].c_str());
        pstMsgTencentInfo->set_is_yellow_year_vip(vIsYellowYearVip[i].c_str());
        pstMsgTencentInfo->set_yellow_vip_level(vYellowVipLevel[i].c_str());
        pstMsgTencentInfo->set_is_yellow_high_vip(vIsYellowHighVip[i].c_str());


    }
    
    return AnsClients(iRet);
}

int CCmdGetMultiTencentInfo::AnsClients(int iRet)
{
    if (iRet)
    {
        CT_WARNING(("CCmdGetMultiTencentInfo ret %d", iRet));
        iRet = RET_OK;
    }
    
    stMsgHead.set_msgret(iRet);
    stMsgHead.set_msgtype(CSMsgDef::EMT_ANSWER);

    if (iRet != RET_OK)
    {
        pstMainCtrl->ReturnMsgHead(stMsgHead, stEnpHead);
        return Done(iRet);
    }

    pstMainCtrl->m_stEncodeBuf.Clear();
    pstMainCtrl->EncodePBMsg(stMsgHead, pstMainCtrl->m_stEncodeBuf);
    pstMainCtrl->EncodePBMsg(stAns, pstMainCtrl->m_stEncodeBuf);
    if (pstMainCtrl->AnswerToClient(stEnpHead, pstMainCtrl->m_stEncodeBuf, true))
    {
        CT_WARNING((""));
        return Done(RET_SYS_ERROR);
    }

    return Done(iRet);
}

